From 05bba06e575829071bce813e12709f9ec477f120 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 19 2015 03:40:33 +0000 Subject: import qemu-kvm-1.5.3-105.el7 --- diff --git a/SOURCES/kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch b/SOURCES/kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch index 234ec1e..39ad67f 100644 --- a/SOURCES/kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch +++ b/SOURCES/kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch @@ -1,15 +1,15 @@ -From 2eae7bb4e94710164926c670334a83bf9d347c2f Mon Sep 17 00:00:00 2001 +From 67c87cd508385158a8a0fb12a430dd19d2883974 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann -Date: Tue, 22 Sep 2015 17:44:53 +0200 -Subject: [PATCH 1/2] CVE-2015-1779: incrementally decode websocket frames +Date: Wed, 20 May 2015 08:39:08 +0200 +Subject: [PATCH 1/6] CVE-2015-1779: incrementally decode websocket frames -Message-id: <1442943894-7638-2-git-send-email-kraxel@redhat.com> -Patchwork-id: 67884 -O-Subject: [RHEL-7.1.z qemu-kvm PATCH 1/2] CVE-2015-1779: incrementally decode websocket frames -Bugzilla: 1205050 -RH-Acked-by: Miroslav Rezanina +Message-id: <1432111149-11644-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 65099 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] CVE-2015-1779: incrementally decode websocket frames +Bugzilla: 1206497 RH-Acked-by: Thomas Huth RH-Acked-by: Petr Matousek +RH-Acked-by: Daniel P. Berrange From: "Daniel P. Berrange" diff --git a/SOURCES/kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch b/SOURCES/kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch index 4d3de63..0647b15 100644 --- a/SOURCES/kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch +++ b/SOURCES/kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch @@ -1,16 +1,16 @@ -From 7721e2e58f7cd2fcf835800622b8a7e1cdeb4557 Mon Sep 17 00:00:00 2001 +From 62121d1bd1f17f5b9822b98f4ee2c9fd159b50e5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann -Date: Tue, 22 Sep 2015 17:44:54 +0200 -Subject: [PATCH 2/2] CVE-2015-1779: limit size of HTTP headers from websockets +Date: Wed, 20 May 2015 08:39:09 +0200 +Subject: [PATCH 2/6] CVE-2015-1779: limit size of HTTP headers from websockets clients -Message-id: <1442943894-7638-3-git-send-email-kraxel@redhat.com> -Patchwork-id: 67885 -O-Subject: [RHEL-7.1.z qemu-kvm PATCH 2/2] CVE-2015-1779: limit size of HTTP headers from websockets clients -Bugzilla: 1205050 -RH-Acked-by: Miroslav Rezanina +Message-id: <1432111149-11644-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 65097 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] CVE-2015-1779: limit size of HTTP headers from websockets clients +Bugzilla: 1206497 RH-Acked-by: Thomas Huth RH-Acked-by: Petr Matousek +RH-Acked-by: Daniel P. Berrange From: "Daniel P. Berrange" diff --git a/SOURCES/kvm-Drop-superfluous-conditionals-around-g_strdup.patch b/SOURCES/kvm-Drop-superfluous-conditionals-around-g_strdup.patch new file mode 100644 index 0000000..ced2cb6 --- /dev/null +++ b/SOURCES/kvm-Drop-superfluous-conditionals-around-g_strdup.patch @@ -0,0 +1,141 @@ +From beb312b86b7ee776bbaea14d3c7625ec8d2d8402 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:19 +0200 +Subject: [PATCH 1/7] Drop superfluous conditionals around g_strdup() + +Message-id: <1441735585-23432-2-git-send-email-armbru@redhat.com> +Patchwork-id: 67708 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/7] Drop superfluous conditionals around g_strdup() +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +Signed-off-by: Markus Armbruster +Reviewed-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Michael Tokarev +(cherry picked from commit 24588100ab39afead7b9a0e9c61182a02320a1b9) +Signed-off-by: Miroslav Rezanina +--- + backends/rng-random.c | 6 +----- + hw/tpm/tpm_passthrough.c | 4 +--- + util/uri.c | 43 +++++++++++++++++-------------------------- + 3 files changed, 19 insertions(+), 34 deletions(-) + +diff --git a/backends/rng-random.c b/backends/rng-random.c +index 68dfc8a..573a64e 100644 +--- a/backends/rng-random.c ++++ b/backends/rng-random.c +@@ -88,11 +88,7 @@ static char *rng_random_get_filename(Object *obj, Error **errp) + { + RndRandom *s = RNG_RANDOM(obj); + +- if (s->filename) { +- return g_strdup(s->filename); +- } +- +- return NULL; ++ return g_strdup(s->filename); + } + + static void rng_random_set_filename(Object *obj, const char *filename, +diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c +index 56e9e0f..2bf3c6f 100644 +--- a/hw/tpm/tpm_passthrough.c ++++ b/hw/tpm/tpm_passthrough.c +@@ -400,9 +400,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) + const char *value; + + value = qemu_opt_get(opts, "cancel-path"); +- if (value) { +- tb->cancel_path = g_strdup(value); +- } ++ tb->cancel_path = g_strdup(value); + + value = qemu_opt_get(opts, "path"); + if (!value) { +diff --git a/util/uri.c b/util/uri.c +index e348c17..bbf2832 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -1736,24 +1736,21 @@ uri_resolve(const char *uri, const char *base) { + goto done; + if ((ref->scheme == NULL) && (ref->path == NULL) && + ((ref->authority == NULL) && (ref->server == NULL))) { +- if (bas->scheme != NULL) +- res->scheme = g_strdup(bas->scheme); ++ res->scheme = g_strdup(bas->scheme); + if (bas->authority != NULL) + res->authority = g_strdup(bas->authority); + else if (bas->server != NULL) { +- res->server = g_strdup(bas->server); +- if (bas->user != NULL) +- res->user = g_strdup(bas->user); +- res->port = bas->port; ++ res->server = g_strdup(bas->server); ++ res->user = g_strdup(bas->user); ++ res->port = bas->port; + } +- if (bas->path != NULL) +- res->path = g_strdup(bas->path); +- if (ref->query != NULL) ++ res->path = g_strdup(bas->path); ++ if (ref->query != NULL) { + res->query = g_strdup (ref->query); +- else if (bas->query != NULL) +- res->query = g_strdup(bas->query); +- if (ref->fragment != NULL) +- res->fragment = g_strdup(ref->fragment); ++ } else { ++ res->query = g_strdup(bas->query); ++ } ++ res->fragment = g_strdup(ref->fragment); + goto step_7; + } + +@@ -1767,13 +1764,10 @@ uri_resolve(const char *uri, const char *base) { + val = uri_to_string(ref); + goto done; + } +- if (bas->scheme != NULL) +- res->scheme = g_strdup(bas->scheme); ++ res->scheme = g_strdup(bas->scheme); + +- if (ref->query != NULL) +- res->query = g_strdup(ref->query); +- if (ref->fragment != NULL) +- res->fragment = g_strdup(ref->fragment); ++ res->query = g_strdup(ref->query); ++ res->fragment = g_strdup(ref->fragment); + + /* + * 4) If the authority component is defined, then the reference is a +@@ -1787,20 +1781,17 @@ uri_resolve(const char *uri, const char *base) { + res->authority = g_strdup(ref->authority); + else { + res->server = g_strdup(ref->server); +- if (ref->user != NULL) +- res->user = g_strdup(ref->user); ++ res->user = g_strdup(ref->user); + res->port = ref->port; + } +- if (ref->path != NULL) +- res->path = g_strdup(ref->path); ++ res->path = g_strdup(ref->path); + goto step_7; + } + if (bas->authority != NULL) + res->authority = g_strdup(bas->authority); + else if (bas->server != NULL) { +- res->server = g_strdup(bas->server); +- if (bas->user != NULL) +- res->user = g_strdup(bas->user); ++ res->server = g_strdup(bas->server); ++ res->user = g_strdup(bas->user); + res->port = bas->port; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Handle-bi-directional-communication-for-fd-migration.patch b/SOURCES/kvm-Handle-bi-directional-communication-for-fd-migration.patch new file mode 100644 index 0000000..827e3ea --- /dev/null +++ b/SOURCES/kvm-Handle-bi-directional-communication-for-fd-migration.patch @@ -0,0 +1,89 @@ +From 24a9e4d46608ccdcec53eeccc40b7a5d3fb7c9c8 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Fri, 16 Jan 2015 17:35:36 +0100 +Subject: [PATCH 04/16] Handle bi-directional communication for fd migration + +Message-id: <1421429737-23581-3-git-send-email-dgilbert@redhat.com> +Patchwork-id: 63333 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/3] Handle bi-directional communication for fd migration +Bugzilla: 1086168 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek + +From: Cristian Klein + +libvirt prefers opening the TCP connection itself, for two reasons. +First, connection failed errors can be detected easier, without having +to parse qemu's error output. +Second, libvirt might be asked to secure the transfer by tunnelling the +communication through an TLS layer. +Therefore, libvirt opens the TCP connection itself and passes an FD to qemu +using QMP and a POSIX-specific mechanism. + +Hence, in order to make the reverse-path work in such cases, qemu needs to +distinguish if the transmitted FD is a socket (reverse-path available) +or not (reverse-path might not be available) and use the corresponding +abstraction. + +Signed-off-by: Cristian Klein +Reviewed-by: Paolo Bonzini +Reviewed-by: Amit Shah +Signed-off-by: Amit Shah +(cherry picked from commit 131fe9b843f9a1e55fcbf2457c9cb25c3711b9d8) +Signed-off-by: Miroslav Rezanina +--- + migration-fd.c | 24 ++++++++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/migration-fd.c b/migration-fd.c +index 3d4613c..3c98c3c 100644 +--- a/migration-fd.c ++++ b/migration-fd.c +@@ -30,13 +30,29 @@ + do { } while (0) + #endif + ++static bool fd_is_socket(int fd) ++{ ++ struct stat stat; ++ int ret = fstat(fd, &stat); ++ if (ret == -1) { ++ /* When in doubt say no */ ++ return false; ++ } ++ return S_ISSOCK(stat.st_mode); ++} ++ + void fd_start_outgoing_migration(MigrationState *s, const char *fdname, Error **errp) + { + int fd = monitor_get_fd(cur_mon, fdname, errp); + if (fd == -1) { + return; + } +- s->file = qemu_fdopen(fd, "wb"); ++ ++ if (fd_is_socket(fd)) { ++ s->file = qemu_fopen_socket(fd, "wb"); ++ } else { ++ s->file = qemu_fdopen(fd, "wb"); ++ } + + migrate_fd_connect(s); + } +@@ -57,7 +73,11 @@ void fd_start_incoming_migration(const char *infd, Error **errp) + DPRINTF("Attempting to start an incoming migration via fd\n"); + + fd = strtol(infd, NULL, 0); +- f = qemu_fdopen(fd, "rb"); ++ if (fd_is_socket(fd)) { ++ f = qemu_fopen_socket(fd, "rb"); ++ } else { ++ f = qemu_fdopen(fd, "rb"); ++ } + if(f == NULL) { + error_setg_errno(errp, errno, "failed to open the source descriptor"); + return; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Python-lang-gdb-script-to-extract-x86_64-guest-vmcor.patch b/SOURCES/kvm-Python-lang-gdb-script-to-extract-x86_64-guest-vmcor.patch new file mode 100644 index 0000000..8de667d --- /dev/null +++ b/SOURCES/kvm-Python-lang-gdb-script-to-extract-x86_64-guest-vmcor.patch @@ -0,0 +1,555 @@ +From 11d85a217f6b3b15710bbc786adebd943774be09 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 20 Feb 2015 09:53:20 +0100 +Subject: [PATCH 14/16] Python-lang gdb script to extract x86_64 guest vmcore + from qemu coredump + +Message-id: <1424426001-3543-2-git-send-email-lersek@redhat.com> +Patchwork-id: 63908 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2 1/2] Python-lang gdb script to extract x86_64 guest vmcore from qemu coredump +Bugzilla: 828493 +RH-Acked-by: Vitaly Kuznetsov +RH-Acked-by: Jeff Nelson +RH-Acked-by: Miroslav Rezanina + +When qemu dies unexpectedly, for example in response to an explicit +abort() call, or (more importantly) when an external signal is delivered +to it that results in a coredump, sometimes it is useful to extract the +guest vmcore from the qemu process' memory image. The guest vmcore might +help understand an emulation problem in qemu, or help debug the guest. + +This script reimplements (and cuts many features of) the +qmp_dump_guest_memory() command in gdb/Python, + + https://sourceware.org/gdb/current/onlinedocs/gdb/Python-API.html + +working off the saved memory image of the qemu process. The docstring in +the patch (serving as gdb help text) describes the limitations relative to +the QMP command. + +Dependencies of qmp_dump_guest_memory() have been reimplemented as needed. +I sought to follow the general structure, sticking to original function +names where possible. However, keeping it simple prevailed in some places. + +The patch has been tested with a 4 VCPU, 768 MB, RHEL-6.4 +(2.6.32-358.el6.x86_64) guest: + +- The script printed + +> guest RAM blocks: +> target_start target_end host_addr message count +> ---------------- ---------------- ---------------- ------- ----- +> 0000000000000000 00000000000a0000 00007f95d0000000 added 1 +> 00000000000a0000 00000000000b0000 00007f960ac00000 added 2 +> 00000000000c0000 00000000000ca000 00007f95d00c0000 added 3 +> 00000000000ca000 00000000000cd000 00007f95d00ca000 joined 3 +> 00000000000cd000 00000000000d0000 00007f95d00cd000 joined 3 +> 00000000000d0000 00000000000f0000 00007f95d00d0000 joined 3 +> 00000000000f0000 0000000000100000 00007f95d00f0000 joined 3 +> 0000000000100000 0000000030000000 00007f95d0100000 joined 3 +> 00000000fc000000 00000000fc800000 00007f960ac00000 added 4 +> 00000000fffe0000 0000000100000000 00007f9618800000 added 5 +> dumping range at 00007f95d0000000 for length 00000000000a0000 +> dumping range at 00007f960ac00000 for length 0000000000010000 +> dumping range at 00007f95d00c0000 for length 000000002ff40000 +> dumping range at 00007f960ac00000 for length 0000000000800000 +> dumping range at 00007f9618800000 for length 0000000000020000 + +- The vmcore was checked with "readelf", comparing the results against a + vmcore written by qmp_dump_guest_memory(): + +> --- theirs 2013-09-12 17:38:59.797289404 +0200 +> +++ mine 2013-09-12 17:39:03.820289404 +0200 +> @@ -27,16 +27,16 @@ +> Type Offset VirtAddr PhysAddr +> FileSiz MemSiz Flags Align +> NOTE 0x0000000000000190 0x0000000000000000 0x0000000000000000 +> - 0x0000000000000ca0 0x0000000000000ca0 0 +> - LOAD 0x0000000000000e30 0x0000000000000000 0x0000000000000000 +> + 0x000000000000001c 0x000000000000001c 0 +> + LOAD 0x00000000000001ac 0x0000000000000000 0x0000000000000000 +> 0x00000000000a0000 0x00000000000a0000 0 +> - LOAD 0x00000000000a0e30 0x0000000000000000 0x00000000000a0000 +> + LOAD 0x00000000000a01ac 0x0000000000000000 0x00000000000a0000 +> 0x0000000000010000 0x0000000000010000 0 +> - LOAD 0x00000000000b0e30 0x0000000000000000 0x00000000000c0000 +> + LOAD 0x00000000000b01ac 0x0000000000000000 0x00000000000c0000 +> 0x000000002ff40000 0x000000002ff40000 0 +> - LOAD 0x000000002fff0e30 0x0000000000000000 0x00000000fc000000 +> + LOAD 0x000000002fff01ac 0x0000000000000000 0x00000000fc000000 +> 0x0000000000800000 0x0000000000800000 0 +> - LOAD 0x00000000307f0e30 0x0000000000000000 0x00000000fffe0000 +> + LOAD 0x00000000307f01ac 0x0000000000000000 0x00000000fffe0000 +> 0x0000000000020000 0x0000000000020000 0 +> +> There is no dynamic section in this file. +> @@ -47,13 +47,6 @@ +> +> No version information found in this file. +> +> -Notes at offset 0x00000190 with length 0x00000ca0: +> +Notes at offset 0x00000190 with length 0x0000001c: +> Owner Data size Description +> - CORE 0x00000150 NT_PRSTATUS (prstatus structure) +> - CORE 0x00000150 NT_PRSTATUS (prstatus structure) +> - CORE 0x00000150 NT_PRSTATUS (prstatus structure) +> - CORE 0x00000150 NT_PRSTATUS (prstatus structure) +> - QEMU 0x000001b0 Unknown note type: (0x00000000) +> - QEMU 0x000001b0 Unknown note type: (0x00000000) +> - QEMU 0x000001b0 Unknown note type: (0x00000000) +> - QEMU 0x000001b0 Unknown note type: (0x00000000) +> + NONE 0x00000005 Unknown note type: (0x00000000) + +- The vmcore was checked with "crash" too, again comparing the results + against a vmcore written by qmp_dump_guest_memory(): + +> --- guest.vmcore.log2 2013-09-12 17:52:27.074289201 +0200 +> +++ example.dump.log2 2013-09-12 17:52:15.904289203 +0200 +> @@ -22,11 +22,11 @@ +> This GDB was configured as "x86_64-unknown-linux-gnu"... +> +> KERNEL: /usr/lib/debug/lib/modules/2.6.32-358.el6.x86_64/vmlinux +> - DUMPFILE: /home/lacos/tmp/guest.vmcore +> + DUMPFILE: /home/lacos/tmp/example.dump +> CPUS: 4 +> - DATE: Thu Sep 12 17:16:11 2013 +> - UPTIME: 00:01:09 +> -LOAD AVERAGE: 0.07, 0.03, 0.00 +> + DATE: Thu Sep 12 17:17:41 2013 +> + UPTIME: 00:00:38 +> +LOAD AVERAGE: 0.18, 0.05, 0.01 +> TASKS: 130 +> NODENAME: localhost.localdomain +> RELEASE: 2.6.32-358.el6.x86_64 +> @@ -38,12 +38,12 @@ +> COMMAND: "swapper" +> TASK: ffffffff81a8d020 (1 of 4) [THREAD_INFO: ffffffff81a00000] +> CPU: 0 +> - STATE: TASK_RUNNING (PANIC) +> + STATE: TASK_RUNNING (ACTIVE) +> + WARNING: panic task not found +> +> crash> bt +> PID: 0 TASK: ffffffff81a8d020 CPU: 0 COMMAND: "swapper" +> - #0 [ffffffff81a01ed0] default_idle at ffffffff8101495d +> - #1 [ffffffff81a01ef0] cpu_idle at ffffffff81009fc6 +> + #0 [ffffffff81a01ef0] cpu_idle at ffffffff81009fc6 +> crash> task ffffffff81a8d020 +> PID: 0 TASK: ffffffff81a8d020 CPU: 0 COMMAND: "swapper" +> struct task_struct { +> @@ -75,7 +75,7 @@ +> prev = 0xffffffff81a8d080 +> }, +> on_rq = 0, +> - exec_start = 8618466836, +> + exec_start = 7469214014, +> sum_exec_runtime = 0, +> vruntime = 0, +> prev_sum_exec_runtime = 0, +> @@ -149,7 +149,7 @@ +> }, +> tasks = { +> next = 0xffff88002d621948, +> - prev = 0xffff880029618f28 +> + prev = 0xffff880023b74488 +> }, +> pushable_tasks = { +> prio = 140, +> @@ -165,7 +165,7 @@ +> } +> }, +> mm = 0x0, +> - active_mm = 0xffff88002929b780, +> + active_mm = 0xffff8800297eb980, +> exit_state = 0, +> exit_code = 0, +> exit_signal = 0, +> @@ -177,7 +177,7 @@ +> sched_reset_on_fork = 0, +> pid = 0, +> tgid = 0, +> - stack_canary = 2483693585637059287, +> + stack_canary = 7266362296181431986, +> real_parent = 0xffffffff81a8d020, +> parent = 0xffffffff81a8d020, +> children = { +> @@ -224,14 +224,14 @@ +> set_child_tid = 0x0, +> clear_child_tid = 0x0, +> utime = 0, +> - stime = 3, +> + stime = 2, +> utimescaled = 0, +> - stimescaled = 3, +> + stimescaled = 2, +> gtime = 0, +> prev_utime = 0, +> prev_stime = 0, +> nvcsw = 0, +> - nivcsw = 1000, +> + nivcsw = 1764, +> start_time = { +> tv_sec = 0, +> tv_nsec = 0 + +- I asked for Dave Anderson's help with verifying the + extracted vmcore, and his comments make me think I should post + this. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 3e16d14fd93ca6059134ba6b4f65c1c3e4cd3a18) +Signed-off-by: Miroslav Rezanina +--- + scripts/dump-guest-memory.py | 339 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 339 insertions(+) + create mode 100644 scripts/dump-guest-memory.py + +diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py +new file mode 100644 +index 0000000..1ed8b67 +--- /dev/null ++++ b/scripts/dump-guest-memory.py +@@ -0,0 +1,339 @@ ++# This python script adds a new gdb command, "dump-guest-memory". It ++# should be loaded with "source dump-guest-memory.py" at the (gdb) ++# prompt. ++# ++# Copyright (C) 2013, Red Hat, Inc. ++# ++# Authors: ++# Laszlo Ersek ++# ++# This work is licensed under the terms of the GNU GPL, version 2 or later. See ++# the COPYING file in the top-level directory. ++# ++# The leading docstring doesn't have idiomatic Python formatting. It is ++# printed by gdb's "help" command (the first line is printed in the ++# "help data" summary), and it should match how other help texts look in ++# gdb. ++ ++import struct ++ ++class DumpGuestMemory(gdb.Command): ++ """Extract guest vmcore from qemu process coredump. ++ ++The sole argument is FILE, identifying the target file to write the ++guest vmcore to. ++ ++This GDB command reimplements the dump-guest-memory QMP command in ++python, using the representation of guest memory as captured in the qemu ++coredump. The qemu process that has been dumped must have had the ++command line option "-machine dump-guest-core=on". ++ ++For simplicity, the "paging", "begin" and "end" parameters of the QMP ++command are not supported -- no attempt is made to get the guest's ++internal paging structures (ie. paging=false is hard-wired), and guest ++memory is always fully dumped. ++ ++Only x86_64 guests are supported. ++ ++The CORE/NT_PRSTATUS and QEMU notes (that is, the VCPUs' statuses) are ++not written to the vmcore. Preparing these would require context that is ++only present in the KVM host kernel module when the guest is alive. A ++fake ELF note is written instead, only to keep the ELF parser of "crash" ++happy. ++ ++Dependent on how busted the qemu process was at the time of the ++coredump, this command might produce unpredictable results. If qemu ++deliberately called abort(), or it was dumped in response to a signal at ++a halfway fortunate point, then its coredump should be in reasonable ++shape and this command should mostly work.""" ++ ++ TARGET_PAGE_SIZE = 0x1000 ++ TARGET_PAGE_MASK = 0xFFFFFFFFFFFFF000 ++ ++ # Various ELF constants ++ EM_X86_64 = 62 # AMD x86-64 target machine ++ ELFDATA2LSB = 1 # little endian ++ ELFCLASS64 = 2 ++ ELFMAG = "\x7FELF" ++ EV_CURRENT = 1 ++ ET_CORE = 4 ++ PT_LOAD = 1 ++ PT_NOTE = 4 ++ ++ # Special value for e_phnum. This indicates that the real number of ++ # program headers is too large to fit into e_phnum. Instead the real ++ # value is in the field sh_info of section 0. ++ PN_XNUM = 0xFFFF ++ ++ # Format strings for packing and header size calculation. ++ ELF64_EHDR = ("4s" # e_ident/magic ++ "B" # e_ident/class ++ "B" # e_ident/data ++ "B" # e_ident/version ++ "B" # e_ident/osabi ++ "8s" # e_ident/pad ++ "H" # e_type ++ "H" # e_machine ++ "I" # e_version ++ "Q" # e_entry ++ "Q" # e_phoff ++ "Q" # e_shoff ++ "I" # e_flags ++ "H" # e_ehsize ++ "H" # e_phentsize ++ "H" # e_phnum ++ "H" # e_shentsize ++ "H" # e_shnum ++ "H" # e_shstrndx ++ ) ++ ELF64_PHDR = ("I" # p_type ++ "I" # p_flags ++ "Q" # p_offset ++ "Q" # p_vaddr ++ "Q" # p_paddr ++ "Q" # p_filesz ++ "Q" # p_memsz ++ "Q" # p_align ++ ) ++ ++ def __init__(self): ++ super(DumpGuestMemory, self).__init__("dump-guest-memory", ++ gdb.COMMAND_DATA, ++ gdb.COMPLETE_FILENAME) ++ self.uintptr_t = gdb.lookup_type("uintptr_t") ++ self.elf64_ehdr_le = struct.Struct("<%s" % self.ELF64_EHDR) ++ self.elf64_phdr_le = struct.Struct("<%s" % self.ELF64_PHDR) ++ ++ def int128_get64(self, val): ++ assert (val["hi"] == 0) ++ return val["lo"] ++ ++ def qtailq_foreach(self, head, field_str): ++ var_p = head["tqh_first"] ++ while (var_p != 0): ++ var = var_p.dereference() ++ yield var ++ var_p = var[field_str]["tqe_next"] ++ ++ def qemu_get_ram_block(self, ram_addr): ++ ram_blocks = gdb.parse_and_eval("ram_list.blocks") ++ for block in self.qtailq_foreach(ram_blocks, "next"): ++ if (ram_addr - block["offset"] < block["length"]): ++ return block ++ raise gdb.GdbError("Bad ram offset %x" % ram_addr) ++ ++ def qemu_get_ram_ptr(self, ram_addr): ++ block = self.qemu_get_ram_block(ram_addr) ++ return block["host"] + (ram_addr - block["offset"]) ++ ++ def memory_region_get_ram_ptr(self, mr): ++ if (mr["alias"] != 0): ++ return (self.memory_region_get_ram_ptr(mr["alias"].dereference()) + ++ mr["alias_offset"]) ++ return self.qemu_get_ram_ptr(mr["ram_addr"] & self.TARGET_PAGE_MASK) ++ ++ def guest_phys_blocks_init(self): ++ self.guest_phys_blocks = [] ++ ++ def guest_phys_blocks_append(self): ++ print "guest RAM blocks:" ++ print ("target_start target_end host_addr message " ++ "count") ++ print ("---------------- ---------------- ---------------- ------- " ++ "-----") ++ ++ current_map_p = gdb.parse_and_eval("address_space_memory.current_map") ++ current_map = current_map_p.dereference() ++ for cur in range(current_map["nr"]): ++ flat_range = (current_map["ranges"] + cur).dereference() ++ mr = flat_range["mr"].dereference() ++ ++ # we only care about RAM ++ if (not mr["ram"]): ++ continue ++ ++ section_size = self.int128_get64(flat_range["addr"]["size"]) ++ target_start = self.int128_get64(flat_range["addr"]["start"]) ++ target_end = target_start + section_size ++ host_addr = (self.memory_region_get_ram_ptr(mr) + ++ flat_range["offset_in_region"]) ++ predecessor = None ++ ++ # find continuity in guest physical address space ++ if (len(self.guest_phys_blocks) > 0): ++ predecessor = self.guest_phys_blocks[-1] ++ predecessor_size = (predecessor["target_end"] - ++ predecessor["target_start"]) ++ ++ # the memory API guarantees monotonically increasing ++ # traversal ++ assert (predecessor["target_end"] <= target_start) ++ ++ # we want continuity in both guest-physical and ++ # host-virtual memory ++ if (predecessor["target_end"] < target_start or ++ predecessor["host_addr"] + predecessor_size != host_addr): ++ predecessor = None ++ ++ if (predecessor is None): ++ # isolated mapping, add it to the list ++ self.guest_phys_blocks.append({"target_start": target_start, ++ "target_end" : target_end, ++ "host_addr" : host_addr}) ++ message = "added" ++ else: ++ # expand predecessor until @target_end; predecessor's ++ # start doesn't change ++ predecessor["target_end"] = target_end ++ message = "joined" ++ ++ print ("%016x %016x %016x %-7s %5u" % ++ (target_start, target_end, host_addr.cast(self.uintptr_t), ++ message, len(self.guest_phys_blocks))) ++ ++ def cpu_get_dump_info(self): ++ # We can't synchronize the registers with KVM post-mortem, and ++ # the bits in (first_x86_cpu->env.hflags) seem to be stale; they ++ # may not reflect long mode for example. Hence just assume the ++ # most common values. This also means that instruction pointer ++ # etc. will be bogus in the dump, but at least the RAM contents ++ # should be valid. ++ self.dump_info = {"d_machine": self.EM_X86_64, ++ "d_endian" : self.ELFDATA2LSB, ++ "d_class" : self.ELFCLASS64} ++ ++ def encode_elf64_ehdr_le(self): ++ return self.elf64_ehdr_le.pack( ++ self.ELFMAG, # e_ident/magic ++ self.dump_info["d_class"], # e_ident/class ++ self.dump_info["d_endian"], # e_ident/data ++ self.EV_CURRENT, # e_ident/version ++ 0, # e_ident/osabi ++ "", # e_ident/pad ++ self.ET_CORE, # e_type ++ self.dump_info["d_machine"], # e_machine ++ self.EV_CURRENT, # e_version ++ 0, # e_entry ++ self.elf64_ehdr_le.size, # e_phoff ++ 0, # e_shoff ++ 0, # e_flags ++ self.elf64_ehdr_le.size, # e_ehsize ++ self.elf64_phdr_le.size, # e_phentsize ++ self.phdr_num, # e_phnum ++ 0, # e_shentsize ++ 0, # e_shnum ++ 0 # e_shstrndx ++ ) ++ ++ def encode_elf64_note_le(self): ++ return self.elf64_phdr_le.pack(self.PT_NOTE, # p_type ++ 0, # p_flags ++ (self.memory_offset - ++ len(self.note)), # p_offset ++ 0, # p_vaddr ++ 0, # p_paddr ++ len(self.note), # p_filesz ++ len(self.note), # p_memsz ++ 0 # p_align ++ ) ++ ++ def encode_elf64_load_le(self, offset, start_hwaddr, range_size): ++ return self.elf64_phdr_le.pack(self.PT_LOAD, # p_type ++ 0, # p_flags ++ offset, # p_offset ++ 0, # p_vaddr ++ start_hwaddr, # p_paddr ++ range_size, # p_filesz ++ range_size, # p_memsz ++ 0 # p_align ++ ) ++ ++ def note_init(self, name, desc, type): ++ # name must include a trailing NUL ++ namesz = (len(name) + 1 + 3) / 4 * 4 ++ descsz = (len(desc) + 3) / 4 * 4 ++ fmt = ("<" # little endian ++ "I" # n_namesz ++ "I" # n_descsz ++ "I" # n_type ++ "%us" # name ++ "%us" # desc ++ % (namesz, descsz)) ++ self.note = struct.pack(fmt, ++ len(name) + 1, len(desc), type, name, desc) ++ ++ def dump_init(self): ++ self.guest_phys_blocks_init() ++ self.guest_phys_blocks_append() ++ self.cpu_get_dump_info() ++ # we have no way to retrieve the VCPU status from KVM ++ # post-mortem ++ self.note_init("NONE", "EMPTY", 0) ++ ++ # Account for PT_NOTE. ++ self.phdr_num = 1 ++ ++ # We should never reach PN_XNUM for paging=false dumps: there's ++ # just a handful of discontiguous ranges after merging. ++ self.phdr_num += len(self.guest_phys_blocks) ++ assert (self.phdr_num < self.PN_XNUM) ++ ++ # Calculate the ELF file offset where the memory dump commences: ++ # ++ # ELF header ++ # PT_NOTE ++ # PT_LOAD: 1 ++ # PT_LOAD: 2 ++ # ... ++ # PT_LOAD: len(self.guest_phys_blocks) ++ # ELF note ++ # memory dump ++ self.memory_offset = (self.elf64_ehdr_le.size + ++ self.elf64_phdr_le.size * self.phdr_num + ++ len(self.note)) ++ ++ def dump_begin(self, vmcore): ++ vmcore.write(self.encode_elf64_ehdr_le()) ++ vmcore.write(self.encode_elf64_note_le()) ++ running = self.memory_offset ++ for block in self.guest_phys_blocks: ++ range_size = block["target_end"] - block["target_start"] ++ vmcore.write(self.encode_elf64_load_le(running, ++ block["target_start"], ++ range_size)) ++ running += range_size ++ vmcore.write(self.note) ++ ++ def dump_iterate(self, vmcore): ++ qemu_core = gdb.inferiors()[0] ++ for block in self.guest_phys_blocks: ++ cur = block["host_addr"] ++ left = block["target_end"] - block["target_start"] ++ print ("dumping range at %016x for length %016x" % ++ (cur.cast(self.uintptr_t), left)) ++ while (left > 0): ++ chunk_size = min(self.TARGET_PAGE_SIZE, left) ++ chunk = qemu_core.read_memory(cur, chunk_size) ++ vmcore.write(chunk) ++ cur += chunk_size ++ left -= chunk_size ++ ++ def create_vmcore(self, filename): ++ vmcore = open(filename, "wb") ++ self.dump_begin(vmcore) ++ self.dump_iterate(vmcore) ++ vmcore.close() ++ ++ def invoke(self, args, from_tty): ++ # Unwittingly pressing the Enter key after the command should ++ # not dump the same multi-gig coredump to the same file. ++ self.dont_repeat() ++ ++ argv = gdb.string_to_argv(args) ++ if (len(argv) != 1): ++ raise gdb.GdbError("usage: dump-guest-memory FILE") ++ ++ self.dump_init() ++ self.create_vmcore(argv[0]) ++ ++DumpGuestMemory() +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Remove-redhat-extensions-from-qmp-events.txt.patch b/SOURCES/kvm-Remove-redhat-extensions-from-qmp-events.txt.patch new file mode 100644 index 0000000..ce8b29f --- /dev/null +++ b/SOURCES/kvm-Remove-redhat-extensions-from-qmp-events.txt.patch @@ -0,0 +1,64 @@ +From c7a7d2970163c29da5445df54b0fabe28021b275 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 27 May 2015 14:50:33 +0200 +Subject: [PATCH 7/8] Remove redhat extensions from qmp-events.txt + +Message-id: <021c5d770a75ff1569b7a43a9a08553c9814214c.1432733950.git.mrezanin@redhat.com> +Patchwork-id: 65136 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] Remove redhat extensions from qmp-events.txt +Bugzilla: 1222833 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Markus Armbruster + +From: Miroslav Rezanina + +We document __com.redhat_reason and __com.redhat_debug_info event members +in qmp-events. We describe them as RHEL 7 extension. This is true for +qemu-kvm pacakge only, qemu-kvm-rhev uses upstream solution. + +Remove this fields from documentation so users do not expect them so they +avoid issues on update to different version of qemu-kvm. + +Signed-off-by: Miroslav Rezanina +--- + QMP/qmp-events.txt | 17 +---------------- + 1 file changed, 1 insertion(+), 16 deletions(-) + +diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt +index ec4e4b9..7d16a6d 100644 +--- a/QMP/qmp-events.txt ++++ b/QMP/qmp-events.txt +@@ -146,28 +146,13 @@ Data: + "ignore": error has been ignored, the job may fail later + "report": error will be reported and the job canceled + "stop": error caused job to be paused +-- "__com.redhat_reason": error reason, this is a RHEL7 extension, it's one of +- the following (json-string): +- "eio": errno EIO +- "eperm": errno EPERM +- "enospc": errno ENOSPC +- "eother": any other errno (other than EIO, EPERM, ENOSPC) +-- "__com.redhat_debug_info": RHEL7 extension containing debug information for +- humans, applications should NOT read any +- information from this member (json-object): +- - "errno": errno value (json-int) +- - "message": error message returned by strerror() (json-string) + + Example: + + { "event": "BLOCK_JOB_ERROR", + "data": { "device": "ide0-hd1", + "operation": "write", +- "action": "stop", +- "__com.redhat_reason": "enospc", +- "__com.redhat_debug_info": { +- "message": "No space left on device", +- "errno": 28 } } ++ "action": "stop" }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + + BLOCK_JOB_READY +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Restore-atapi_dma-flag-across-migration.patch b/SOURCES/kvm-Restore-atapi_dma-flag-across-migration.patch new file mode 100644 index 0000000..ccce520 --- /dev/null +++ b/SOURCES/kvm-Restore-atapi_dma-flag-across-migration.patch @@ -0,0 +1,47 @@ +From 26631da9bba6bcf000b4a87715cb3e8364afc373 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 10 Feb 2015 11:45:35 +0100 +Subject: [PATCH 09/16] Restore atapi_dma flag across migration + +Message-id: <1423568736-19538-2-git-send-email-dgilbert@redhat.com> +Patchwork-id: 63778 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] Restore atapi_dma flag across migration +Bugzilla: 892258 +RH-Acked-by: Juan Quintela +RH-Acked-by: Laszlo Ersek +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi + +From: "Dr. David Alan Gilbert" + +If a migration happens just after the guest has kicked +off an ATAPI command and kicked off DMA, we lose the atapi_dma +flag, and the destination tries to complete the command as PIO +rather than DMA. This upsets Linux; modern libata based kernels +stumble and recover OK, older kernels end up passing bad data +to userspace. + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +(cherry picked from commit 819fa276311ce328a8e38ad9306c1093961b3f4b) +Signed-off-by: Miroslav Rezanina +--- + hw/ide/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 24a1708..9a22425 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -2283,6 +2283,7 @@ static int ide_drive_pio_post_load(void *opaque, int version_id) + s->end_transfer_func = transfer_end_table[s->end_transfer_fn_idx]; + s->data_ptr = s->io_buffer + s->cur_io_buffer_offset; + s->data_end = s->data_ptr + s->cur_io_buffer_len; ++ s->atapi_dma = s->feature & 1; /* as per cmd_packet */ + + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ahci.c-mask-unused-flags-when-reading-size-PRDT-DBC.patch b/SOURCES/kvm-ahci.c-mask-unused-flags-when-reading-size-PRDT-DBC.patch new file mode 100644 index 0000000..4304ad2 --- /dev/null +++ b/SOURCES/kvm-ahci.c-mask-unused-flags-when-reading-size-PRDT-DBC.patch @@ -0,0 +1,92 @@ +From e4edeb73e3b9b1ba4efbf18ddb687fb210fd57f8 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Fri, 26 Jun 2015 21:52:46 +0200 +Subject: [PATCH 1/2] ahci.c: mask unused flags when reading size PRDT DBC + +Message-id: <1435355567-29641-2-git-send-email-jsnow@redhat.com> +Patchwork-id: 66535 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] ahci.c: mask unused flags when reading size PRDT DBC +Bugzilla: 1205100 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Juan Quintela +RH-Acked-by: Stefan Hajnoczi + +From: Reza Jelveh + +The data byte count(DBC) read from the description information is defined for +bits 21:00. Bits 30:22 are reserved and bit 31 is the Interrupt on Completion +(I) flag. + +Completion interrupts are triggered after every transaction instead of on +I-flag in QEMU. tbl_entry_size is a signed integer and improperly reading the +DBC leads to a negative offset that causes sglist allocation to fail. + +Signed-off-by: Reza Jelveh +Reviewed-by: Alexander Graf +Reviewed-by: Kevin Wolf +Reviewed-by: John Snow +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit d02f8adc6d2a178bcbf77d0413f9a96fdbed53f0) +Signed-off-by: John Snow +Signed-off-by: Miroslav Rezanina +--- + hw/ide/ahci.c | 11 ++++++++--- + hw/ide/ahci.h | 2 ++ + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index 011e796..7f3927a 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -635,6 +635,11 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) + } + } + ++static int prdt_tbl_entry_size(const AHCI_SG *tbl) ++{ ++ return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1; ++} ++ + static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + { + AHCICmdHdr *cmd = ad->cur_cmd; +@@ -675,7 +680,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + sum = 0; + for (i = 0; i < sglist_alloc_hint; i++) { + /* flags_size is zero-based */ +- tbl_entry_size = (le32_to_cpu(tbl[i].flags_size) + 1); ++ tbl_entry_size = prdt_tbl_entry_size(&tbl[i]); + if (offset <= (sum + tbl_entry_size)) { + off_idx = i; + off_pos = offset - sum; +@@ -693,12 +698,12 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + + qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->dma); + qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos), +- le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos); ++ prdt_tbl_entry_size(&tbl[off_idx]) - off_pos); + + for (i = off_idx + 1; i < sglist_alloc_hint; i++) { + /* flags_size is zero-based */ + qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), +- le32_to_cpu(tbl[i].flags_size) + 1); ++ prdt_tbl_entry_size(&tbl[i])); + } + } + +diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h +index 85f37fe..47c0961 100644 +--- a/hw/ide/ahci.h ++++ b/hw/ide/ahci.h +@@ -201,6 +201,8 @@ + + #define AHCI_COMMAND_TABLE_ACMD 0x40 + ++#define AHCI_PRDT_SIZE_MASK 0x3fffff ++ + #define IDE_FEATURE_DMA 1 + + #define READ_FPDMA_QUEUED 0x60 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-always-update-the-MPX-model-specific-register.patch b/SOURCES/kvm-always-update-the-MPX-model-specific-register.patch new file mode 100644 index 0000000..5f8f5f9 --- /dev/null +++ b/SOURCES/kvm-always-update-the-MPX-model-specific-register.patch @@ -0,0 +1,58 @@ +From 7ed89963702e6c53c20864b564a5b43712a38ccd Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:24 +0200 +Subject: [PATCH 04/10] kvm: always update the MPX model specific register + +Message-id: <1435260689-9556-4-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66501 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/8] kvm: always update the MPX model specific register +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: Paolo Bonzini + +The original patch from Liu Jinsong restricted them to reset or full +state updates, but that's unnecessary (and wrong) since the BNDCFGS +MSR has no side effects. + +Cc: Liu Jinsong +Signed-off-by: Paolo Bonzini +(cherry picked from commit 439d19f2922ac409ee224bc1e5522cee7009d829) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina + +Conflicts: + target-i386/kvm.c +--- + target-i386/kvm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index 6d9aa63..bbbbac0 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -1155,6 +1155,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + kvm_msr_entry_set(&msrs[n++], MSR_IA32_MISC_ENABLE, + env->msr_ia32_misc_enable); + } ++ if (has_msr_bndcfgs) { ++ kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs); ++ } + #ifdef TARGET_X86_64 + if (lm_capable_kernel) { + kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); +@@ -1266,9 +1269,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + MSR_MTRRphysMask(i), env->mtrr_var[i].mask); + } + } +- if (has_msr_bndcfgs) { +- kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs); +- } + } + if (env->mcg_cap) { + int i; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch b/SOURCES/kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch new file mode 100644 index 0000000..82197a6 --- /dev/null +++ b/SOURCES/kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch @@ -0,0 +1,118 @@ +From e44bfb41173183a85bb6fa94a6f48486ac4ab0a2 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 10 Feb 2015 11:45:36 +0100 +Subject: [PATCH 10/16] atapi migration: Throw recoverable error to avoid + recovery + +Message-id: <1423568736-19538-3-git-send-email-dgilbert@redhat.com> +Patchwork-id: 63779 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] atapi migration: Throw recoverable error to avoid recovery +Bugzilla: 892258 +RH-Acked-by: Juan Quintela +RH-Acked-by: Laszlo Ersek +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi + +From: "Dr. David Alan Gilbert" + +(With the previous atapi_dma flag recovery) +If migration happens between the ATAPI command being written and the +bmdma being started, the DMA is dropped. Eventually the guest times +out and recovers, but that can take many seconds. +(This is rare, on a pingpong reading the CD continuously I hit +this about ~1/30-1/50 migrates) + +I don't think we've got enough state to be able to recover safely +at this point, so I throw a 'medium error, no seek complete' +that I'm assuming guests will try and recover from an apparently +dirty CD. + +OK, it's a hack, the real solution is probably to push a lot of +ATAPI state into the migration stream, but this is a fix that +works with no stream changes. Tested only on Linux (both RHEL5 +(pre-libata) and RHEL7). + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: John Snow +Signed-off-by: Kevin Wolf +(cherry picked from commit a71754e5b03fd3b8b8c6d3bc2a39f75bead729de) +Signed-off-by: Miroslav Rezanina +--- + hw/ide/atapi.c | 17 +++++++++++++++++ + hw/ide/internal.h | 2 ++ + hw/ide/pci.c | 11 +++++++++++ + 3 files changed, 30 insertions(+) + +diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c +index 05e60b1..46a2c26 100644 +--- a/hw/ide/atapi.c ++++ b/hw/ide/atapi.c +@@ -393,6 +393,23 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, + } + } + ++ ++/* Called by *_restart_bh when the transfer function points ++ * to ide_atapi_cmd ++ */ ++void ide_atapi_dma_restart(IDEState *s) ++{ ++ /* ++ * I'm not sure we have enough stored to restart the command ++ * safely, so give the guest an error it should recover from. ++ * I'm assuming most guests will try to recover from something ++ * listed as a medium error on a CD; it seems to work on Linux. ++ * This would be more of a problem if we did any other type of ++ * DMA operation. ++ */ ++ ide_atapi_cmd_error(s, MEDIUM_ERROR, ASC_NO_SEEK_COMPLETE); ++} ++ + static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index, + uint16_t profile) + { +diff --git a/hw/ide/internal.h b/hw/ide/internal.h +index 048a052..0a2d6bc 100644 +--- a/hw/ide/internal.h ++++ b/hw/ide/internal.h +@@ -289,6 +289,7 @@ typedef struct IDEDMAOps IDEDMAOps; + #define ATAPI_INT_REASON_TAG 0xf8 + + /* same constants as bochs */ ++#define ASC_NO_SEEK_COMPLETE 0x02 + #define ASC_ILLEGAL_OPCODE 0x20 + #define ASC_LOGICAL_BLOCK_OOR 0x21 + #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +@@ -536,6 +537,7 @@ void ide_dma_error(IDEState *s); + + void ide_atapi_cmd_ok(IDEState *s); + void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); ++void ide_atapi_dma_restart(IDEState *s); + void ide_atapi_io_error(IDEState *s, int ret); + + void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); +diff --git a/hw/ide/pci.c b/hw/ide/pci.c +index 635a364..cf7acb0 100644 +--- a/hw/ide/pci.c ++++ b/hw/ide/pci.c +@@ -220,6 +220,17 @@ static void bmdma_restart_bh(void *opaque) + } + } else if (error_status & BM_STATUS_RETRY_FLUSH) { + ide_flush_cache(bmdma_active_if(bm)); ++ } else { ++ IDEState *s = bmdma_active_if(bm); ++ ++ /* ++ * We've not got any bits to tell us about ATAPI - but ++ * we do have the end_transfer_func that tells us what ++ * we're trying to do. ++ */ ++ if (s->end_transfer_func == ide_atapi_cmd) { ++ ide_atapi_dma_restart(s); ++ } + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch b/SOURCES/kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch index 3a7ce94..827e23b 100644 --- a/SOURCES/kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch +++ b/SOURCES/kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch @@ -1,4 +1,4 @@ -From 0f918da30dbb71e68e7fad4a2da8983b25536233 Mon Sep 17 00:00:00 2001 +From d37475eb567b61ce6a18f9fcbf35eb929be8d99f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Jun 2015 10:45:29 +0200 Subject: [PATCH] atomics: add explicit compiler fence in __atomic memory @@ -7,11 +7,15 @@ Subject: [PATCH] atomics: add explicit compiler fence in __atomic memory Message-id: <1434710730-26183-1-git-send-email-pbonzini@redhat.com> Patchwork-id: 66333 O-Subject: [RHEL7.2/7.1.z qemu-kvm PATCH] atomics: add explicit compiler fence in __atomic memory barriers -Bugzilla: 1233643 +Bugzilla: 1142857 RH-Acked-by: Fam Zheng RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Dr. David Alan Gilbert +Bugzilla: 1142857 (aka 8*10^6/7) + +Brew build: 9393725 + __atomic_thread_fence does not include a compiler barrier; in the C++11 memory model, fences take effect in combination with other atomic operations. GCC implements this by making __atomic_load and diff --git a/SOURCES/kvm-block-Add-Error-argument-to-bdrv_refresh_limits.patch b/SOURCES/kvm-block-Add-Error-argument-to-bdrv_refresh_limits.patch new file mode 100644 index 0000000..38757ff --- /dev/null +++ b/SOURCES/kvm-block-Add-Error-argument-to-bdrv_refresh_limits.patch @@ -0,0 +1,307 @@ +From 1aac494dfcc4f96e04f3ad8bc14db8f17c48626f Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 17 Mar 2015 13:02:48 +0100 +Subject: [PATCH 13/16] block: Add Error argument to bdrv_refresh_limits() + +Message-id: <1424365599-9801-2-git-send-email-stefanha@redhat.com> +Patchwork-id: 63914 +O-Subject: [RHEL-7.1 qemu-kvm PATCH 1/2] block: Add Error argument to bdrv_refresh_limits() +Bugzilla: 1184363 +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow +RH-Acked-by: Laszlo Ersek + +From: Kevin Wolf + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 3baca891391afba154e250f5a108c6bab6c92cf9) +Signed-off-by: Stefan Hajnoczi + +Conflicts: + block.c + +bdrv_set_backing_hd() does not exist downstream so there are extra +bdrv_refresh_limits() occurrences downstream. They pass a NULL errp +argument as bdrv_set_backing_hd() would. + + block/iscsi.c + +Context conflict, easy to resolve. + + block/raw_bsd.c + +Does not exist downstream, apply change to block/raw.c instead. +--- + block.c | 35 ++++++++++++++++++++++++----------- + block/iscsi.c | 4 +--- + block/qcow2.c | 4 +--- + block/qed.c | 4 +--- + block/raw-posix.c | 4 +--- + block/raw.c | 3 +-- + block/stream.c | 2 +- + block/vmdk.c | 4 +--- + include/block/block.h | 2 +- + include/block/block_int.h | 2 +- + 10 files changed, 33 insertions(+), 31 deletions(-) + +diff --git a/block.c b/block.c +index 21418a6..89ab829 100644 +--- a/block.c ++++ b/block.c +@@ -462,19 +462,24 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options, + return ret; + } + +-int bdrv_refresh_limits(BlockDriverState *bs) ++void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) + { + BlockDriver *drv = bs->drv; ++ Error *local_err = NULL; + + memset(&bs->bl, 0, sizeof(bs->bl)); + + if (!drv) { +- return 0; ++ return; + } + + /* Take some limits from the children as a default */ + if (bs->file) { +- bdrv_refresh_limits(bs->file); ++ bdrv_refresh_limits(bs->file, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } + bs->bl.opt_transfer_length = bs->file->bl.opt_transfer_length; + bs->bl.opt_mem_alignment = bs->file->bl.opt_mem_alignment; + } else { +@@ -482,7 +487,11 @@ int bdrv_refresh_limits(BlockDriverState *bs) + } + + if (bs->backing_hd) { +- bdrv_refresh_limits(bs->backing_hd); ++ bdrv_refresh_limits(bs->backing_hd, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } + bs->bl.opt_transfer_length = + MAX(bs->bl.opt_transfer_length, + bs->backing_hd->bl.opt_transfer_length); +@@ -493,10 +502,8 @@ int bdrv_refresh_limits(BlockDriverState *bs) + + /* Then let the driver override it */ + if (drv->bdrv_refresh_limits) { +- return drv->bdrv_refresh_limits(bs); ++ drv->bdrv_refresh_limits(bs, errp); + } +- +- return 0; + } + + /* +@@ -856,7 +863,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + goto free_and_fail; + } + +- bdrv_refresh_limits(bs); ++ bdrv_refresh_limits(bs, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ ret = -EINVAL; ++ goto free_and_fail; ++ } ++ + assert(bdrv_opt_mem_align(bs) != 0); + assert((bs->request_alignment != 0) || bs->sg); + +@@ -1048,7 +1061,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + } + + /* Recalculate the BlockLimits with the backing file */ +- bdrv_refresh_limits(bs); ++ bdrv_refresh_limits(bs, NULL); + + return 0; + } +@@ -1483,7 +1496,7 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state) + BDRV_O_CACHE_WB); + reopen_state->bs->read_only = !(reopen_state->flags & BDRV_O_RDWR); + +- bdrv_refresh_limits(reopen_state->bs); ++ bdrv_refresh_limits(reopen_state->bs, NULL); + } + + /* +@@ -2398,7 +2411,7 @@ int bdrv_drop_intermediate(BlockDriverState *active, BlockDriverState *top, + } + new_top_bs->backing_hd = base_bs; + +- bdrv_refresh_limits(new_top_bs); ++ bdrv_refresh_limits(new_top_bs, NULL); + + QSIMPLEQ_FOREACH_SAFE(intermediate_state, &states_to_delete, entry, next) { + /* so that bdrv_close() does not recursively close the chain */ +diff --git a/block/iscsi.c b/block/iscsi.c +index 3d61dd7..2a4ab22 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1550,7 +1550,7 @@ static void iscsi_close(BlockDriverState *bs) + memset(iscsilun, 0, sizeof(IscsiLun)); + } + +-static int iscsi_refresh_limits(BlockDriverState *bs) ++static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) + { + IscsiLun *iscsilun = bs->opaque; + +@@ -1576,8 +1576,6 @@ static int iscsi_refresh_limits(BlockDriverState *bs) + bs->bl.opt_transfer_length = sector_lun2qemu(iscsilun->bl.opt_xfer_len, + iscsilun); + } +- +- return 0; + } + + /* We have nothing to do for iSCSI reopen, stub just returns +diff --git a/block/qcow2.c b/block/qcow2.c +index 43e54d6..005d513 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -848,13 +848,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + return ret; + } + +-static int qcow2_refresh_limits(BlockDriverState *bs) ++static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp) + { + BDRVQcowState *s = bs->opaque; + + bs->bl.write_zeroes_alignment = s->cluster_sectors; +- +- return 0; + } + + static int qcow2_set_key(BlockDriverState *bs, const char *key) +diff --git a/block/qed.c b/block/qed.c +index d1de0a2..5793fca 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -507,13 +507,11 @@ out: + return ret; + } + +-static int bdrv_qed_refresh_limits(BlockDriverState *bs) ++static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp) + { + BDRVQEDState *s = bs->opaque; + + bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS; +- +- return 0; + } + + /* We have nothing to do for QED reopen, stubs just return +diff --git a/block/raw-posix.c b/block/raw-posix.c +index af526ca..46b941b 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -588,14 +588,12 @@ static void raw_reopen_abort(BDRVReopenState *state) + state->opaque = NULL; + } + +-static int raw_refresh_limits(BlockDriverState *bs) ++static void raw_refresh_limits(BlockDriverState *bs, Error **errp) + { + BDRVRawState *s = bs->opaque; + + raw_probe_alignment(bs, s->fd, errp); + bs->bl.opt_mem_alignment = s->buf_align; +- +- return 0; + } + + static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb) +diff --git a/block/raw.c b/block/raw.c +index eeadba5..a750359 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -58,10 +58,9 @@ static int64_t raw_getlength(BlockDriverState *bs) + return bdrv_getlength(bs->file); + } + +-static int raw_refresh_limits(BlockDriverState *bs) ++static void raw_refresh_limits(BlockDriverState *bs, Error **errp) + { + bs->bl = bs->file->bl; +- return 0; + } + + static int raw_truncate(BlockDriverState *bs, int64_t offset) +diff --git a/block/stream.c b/block/stream.c +index 367120d..4e4436c 100644 +--- a/block/stream.c ++++ b/block/stream.c +@@ -72,7 +72,7 @@ static void close_unused_images(BlockDriverState *top, BlockDriverState *base, + } + top->backing_hd = base; + +- bdrv_refresh_limits(top); ++ bdrv_refresh_limits(top, NULL); + } + + static void coroutine_fn stream_run(void *opaque) +diff --git a/block/vmdk.c b/block/vmdk.c +index cfcaa84..24e9458 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -954,7 +954,7 @@ fail: + } + + +-static int vmdk_refresh_limits(BlockDriverState *bs) ++static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp) + { + BDRVVmdkState *s = bs->opaque; + int i; +@@ -966,8 +966,6 @@ static int vmdk_refresh_limits(BlockDriverState *bs) + s->extents[i].cluster_sectors); + } + } +- +- return 0; + } + + /** +diff --git a/include/block/block.h b/include/block/block.h +index c79a1e1..3170cbc 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -254,7 +254,7 @@ int64_t bdrv_nb_sectors(BlockDriverState *bs); + int64_t bdrv_getlength(BlockDriverState *bs); + int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); + void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); +-int bdrv_refresh_limits(BlockDriverState *bs); ++void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); + int bdrv_commit(BlockDriverState *bs); + int bdrv_commit_all(void); + int bdrv_change_backing_file(BlockDriverState *bs, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index e6874b4..3f86649 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -213,7 +213,7 @@ struct BlockDriver { + int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag); + bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag); + +- int (*bdrv_refresh_limits)(BlockDriverState *bs); ++ void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp); + + /* + * Returns 1 if newly created images are guaranteed to contain only +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Add-qemu_-try_-blockalign0.patch b/SOURCES/kvm-block-Add-qemu_-try_-blockalign0.patch new file mode 100644 index 0000000..1c0069d --- /dev/null +++ b/SOURCES/kvm-block-Add-qemu_-try_-blockalign0.patch @@ -0,0 +1,81 @@ +From ad8bc0d8901415eeea7bb27ef26f197918be0752 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:09 +0200 +Subject: [PATCH 15/42] block: Add qemu_{,try_}blockalign0() + +Message-id: <1434212556-3927-16-git-send-email-mreitz@redhat.com> +Patchwork-id: 66034 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 15/42] block: Add qemu_{,try_}blockalign0() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +These functions call their non-0-counterparts and then fill the +allocated buffer with 0 (if the allocation has been successful). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 9ebd84480583bb6d9a7666c079d99ff3266c423d) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block.c | 16 ++++++++++++++++ + include/block/block.h | 2 ++ + 2 files changed, 18 insertions(+) + +diff --git a/block.c b/block.c +index 1afa544..22ab762 100644 +--- a/block.c ++++ b/block.c +@@ -5178,6 +5178,11 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size) + return qemu_memalign(bdrv_opt_mem_align(bs), size); + } + ++void *qemu_blockalign0(BlockDriverState *bs, size_t size) ++{ ++ return memset(qemu_blockalign(bs, size), 0, size); ++} ++ + void *qemu_try_blockalign(BlockDriverState *bs, size_t size) + { + size_t align = bdrv_opt_mem_align(bs); +@@ -5191,6 +5196,17 @@ void *qemu_try_blockalign(BlockDriverState *bs, size_t size) + return qemu_try_memalign(align, size); + } + ++void *qemu_try_blockalign0(BlockDriverState *bs, size_t size) ++{ ++ void *mem = qemu_try_blockalign(bs, size); ++ ++ if (mem) { ++ memset(mem, 0, size); ++ } ++ ++ return mem; ++} ++ + /* + * Check if all memory in this vector is sector aligned. + */ +diff --git a/include/block/block.h b/include/block/block.h +index 7b538b7..8339cac 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -417,7 +417,9 @@ void bdrv_img_create(const char *filename, const char *fmt, + size_t bdrv_opt_mem_align(BlockDriverState *bs); + void bdrv_set_guest_block_size(BlockDriverState *bs, int align); + void *qemu_blockalign(BlockDriverState *bs, size_t size); ++void *qemu_blockalign0(BlockDriverState *bs, size_t size); + void *qemu_try_blockalign(BlockDriverState *bs, size_t size); ++void *qemu_try_blockalign0(BlockDriverState *bs, size_t size); + bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); + + struct HBitmapIter; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Allow-JSON-filenames.patch b/SOURCES/kvm-block-Allow-JSON-filenames.patch new file mode 100644 index 0000000..bbc27d3 --- /dev/null +++ b/SOURCES/kvm-block-Allow-JSON-filenames.patch @@ -0,0 +1,89 @@ +From c2eb29efe61ffe88d3aff449446a9ac0f0f045a5 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Tue, 2 Jun 2015 09:46:37 +0200 +Subject: [PATCH 3/4] block: Allow JSON filenames + +Message-id: <1433238397-2500-3-git-send-email-rjones@redhat.com> +Patchwork-id: 65279 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] block: Allow JSON filenames +Bugzilla: 1226697 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +From: Max Reitz + +If the filename given to bdrv_open() is prefixed with "json:", parse the +rest as a JSON object and merge the result into the options QDict. If +there are conflicts, the options QDict takes precedence. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + block.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/block.c b/block.c +index 45543d5..f2caf20 100644 +--- a/block.c ++++ b/block.c +@@ -1085,6 +1085,33 @@ static void extract_subqdict(QDict *src, QDict **dst, const char *start) + } + } + ++static QDict *parse_json_filename(const char *filename, Error **errp) ++{ ++ QObject *options_obj; ++ QDict *options; ++ int ret; ++ ++ ret = strstart(filename, "json:", &filename); ++ assert(ret); ++ ++ options_obj = qobject_from_json(filename); ++ if (!options_obj) { ++ error_setg(errp, "Could not parse the JSON options"); ++ return NULL; ++ } ++ ++ if (qobject_type(options_obj) != QTYPE_QDICT) { ++ qobject_decref(options_obj); ++ error_setg(errp, "Invalid JSON object given"); ++ return NULL; ++ } ++ ++ options = qobject_to_qdict(options_obj); ++ qdict_flatten(options); ++ ++ return options; ++} ++ + /* + * Opens a disk image (raw, qcow2, vmdk, ...) + * +@@ -1109,6 +1136,20 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + options = qdict_new(); + } + ++ if (filename && g_str_has_prefix(filename, "json:")) { ++ QDict *json_options = parse_json_filename(filename, &local_err); ++ if (local_err) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ /* Options given in the filename have lower priority than options ++ * specified directly */ ++ qdict_join(options, json_options, false); ++ QDECREF(json_options); ++ filename = NULL; ++ } ++ + bs->options = options; + options = qdict_clone_shallow(options); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Catch-bs-drv-in-bdrv_check.patch b/SOURCES/kvm-block-Catch-bs-drv-in-bdrv_check.patch new file mode 100644 index 0000000..0bada8d --- /dev/null +++ b/SOURCES/kvm-block-Catch-bs-drv-in-bdrv_check.patch @@ -0,0 +1,48 @@ +From c7d5655eea99e3a62075c5ca067a6d8f670ddf9d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:00 +0200 +Subject: [PATCH 06/42] block: Catch !bs->drv in bdrv_check() + +Message-id: <1434212556-3927-7-git-send-email-mreitz@redhat.com> +Patchwork-id: 66025 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 06/42] block: Catch !bs->drv in bdrv_check() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +qemu-img check calls bdrv_check() twice if the first run repaired some +inconsistencies. If the first run however again triggered corruption +prevention (on qcow2) due to very bad inconsistencies, bs->drv may be +NULL afterwards. Thus, bdrv_check() should check whether bs->drv is set. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 908bcd540f489f7adf2d804347905b0025d808d3) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block.c b/block.c +index caea2ea..1afa544 100644 +--- a/block.c ++++ b/block.c +@@ -1998,6 +1998,9 @@ bool bdrv_dev_is_medium_locked(BlockDriverState *bs) + */ + int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix) + { ++ if (bs->drv == NULL) { ++ return -ENOMEDIUM; ++ } + if (bs->drv->bdrv_check == NULL) { + return -ENOTSUP; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Don-t-probe-for-unknown-backing-file-format.patch b/SOURCES/kvm-block-Don-t-probe-for-unknown-backing-file-format.patch new file mode 100644 index 0000000..c77ffc3 --- /dev/null +++ b/SOURCES/kvm-block-Don-t-probe-for-unknown-backing-file-format.patch @@ -0,0 +1,203 @@ +From a0f50f0877463e9370ffa411bd826d7c704ab9fe Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:30 +0200 +Subject: [PATCH 36/42] block: Don't probe for unknown backing file format + +Message-id: <1434212556-3927-37-git-send-email-mreitz@redhat.com> +Patchwork-id: 66055 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 36/42] block: Don't probe for unknown backing file format +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +If a qcow2 image specifies a backing file format that doesn't correspond +to any format driver that qemu knows, we shouldn't fall back to probing, +but simply error out. + +Not looking up the backing file driver in bdrv_open_backing_file(), but +just filling in the "driver" option if it isn't there moves us closer to +the goal of having everything in QDict options and gets us the error +handling of bdrv_open(), which correctly refuses unknown drivers. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Message-id: 1416935562-7760-4-git-send-email-kwolf@redhat.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit c5f6e493bb5339d244eae5d3f21c5b6d73996739) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block.c + tests/qemu-iotests/114.out + +Downstream is missing a check whether the driver specified by the +"driver" option is actually valid (if it is not, it will be probed +anyway); this check is introduced upstream by +17b005f1d422d4581f8ce95b75d603deb081f4f3, but that commit has a couple +of dependencies and relies on a code path that is very different from +downstream (e.g. not bdrv_file_open() anymore). So I just introduced the +check in this patch. + +Also, the different code paths upstream and downstream result in the +error message missing the "Could not open backing file:" part, which +means that 114.out has to be fixed up. + +Signed-off-by: Max Reitz +--- + block.c | 12 ++++++--- + tests/qemu-iotests/114 | 61 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/114.out | 13 ++++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 83 insertions(+), 4 deletions(-) + create mode 100755 tests/qemu-iotests/114 + create mode 100644 tests/qemu-iotests/114.out + +diff --git a/block.c b/block.c +index fa6e192..e36fa2f 100644 +--- a/block.c ++++ b/block.c +@@ -1010,7 +1010,6 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + { + char backing_filename[PATH_MAX]; + int back_flags, ret; +- BlockDriver *back_drv = NULL; + Error *local_err = NULL; + + if (bs->backing_hd != NULL) { +@@ -1036,8 +1035,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + + bs->backing_hd = bdrv_new("", &error_abort); + +- if (bs->backing_format[0] != '\0') { +- back_drv = bdrv_find_format(bs->backing_format); ++ if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) { ++ qdict_put(options, "driver", qstring_from_str(bs->backing_format)); + } + + /* backing files always opened read-only */ +@@ -1046,7 +1045,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + + ret = bdrv_open(bs->backing_hd, + *backing_filename ? backing_filename : NULL, options, +- back_flags, back_drv, &local_err); ++ back_flags, NULL, &local_err); + if (ret < 0) { + bdrv_unref(bs->backing_hd); + bs->backing_hd = NULL; +@@ -1244,6 +1243,11 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + if (drvname) { + drv = bdrv_find_format(drvname); + qdict_del(options, "driver"); ++ if (!drv) { ++ error_setg(errp, "Unknown driver '%s'", drvname); ++ ret = -EINVAL; ++ goto unlink_and_fail; ++ } + } + + if (!drv) { +diff --git a/tests/qemu-iotests/114 b/tests/qemu-iotests/114 +new file mode 100755 +index 0000000..d02e7ff +--- /dev/null ++++ b/tests/qemu-iotests/114 +@@ -0,0 +1,61 @@ ++#!/bin/bash ++# ++# Test invalid backing file format in qcow2 images ++# ++# Copyright (C) 2014 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=kwolf@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto generic ++_supported_os Linux ++ ++ ++TEST_IMG="$TEST_IMG.base" _make_test_img 64M ++_make_test_img -b "$TEST_IMG.base" 64M ++ ++# Set an invalid backing file format ++$PYTHON qcow2.py "$TEST_IMG" add-header-ext 0xE2792ACA "foo" ++_img_info ++ ++# Try opening the image. Should fail (and not probe) in the first case, but ++# overriding the backing file format should be possible. ++$QEMU_IO -c "open $TEST_IMG" -c "read 0 4k" 2>&1 | _filter_qemu_io | _filter_testdir ++$QEMU_IO -c "open -o backing.driver=$IMGFMT $TEST_IMG" -c "read 0 4k" | _filter_qemu_io ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out +new file mode 100644 +index 0000000..de8f529 +--- /dev/null ++++ b/tests/qemu-iotests/114.out +@@ -0,0 +1,13 @@ ++QA output created by 114 ++Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base' ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 64M (67108864 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/t.IMGFMT.base ++backing file format: foo ++qemu-io: can't open device TEST_DIR/t.qcow2: Unknown driver 'foo' ++read 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 695ab02..5867cf7 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -88,3 +88,4 @@ + 105 rw auto quick + 107 rw auto quick + 108 rw auto quick ++114 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Drop-superfluous-conditionals-around-g_free.patch b/SOURCES/kvm-block-Drop-superfluous-conditionals-around-g_free.patch new file mode 100644 index 0000000..e90bae7 --- /dev/null +++ b/SOURCES/kvm-block-Drop-superfluous-conditionals-around-g_free.patch @@ -0,0 +1,75 @@ +From 348879493233388280a097c75f5a371512d7918b Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:23 +0200 +Subject: [PATCH 23/30] block: Drop superfluous conditionals around g_free() + +Message-id: <1434022828-13037-17-git-send-email-rjones@redhat.com> +Patchwork-id: 65853 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 16/21] block: Drop superfluous conditionals around g_free() +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Stefan Hajnoczi + +Upstream-status: f7047c2daf760385edf83df10be4259bea190e75 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 3 +-- + block/iscsi.c | 4 +--- + hw/block/onenand.c | 4 +--- + 3 files changed, 3 insertions(+), 8 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index e48cc87..d95789a 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -614,8 +614,7 @@ static void curl_readv_bh_cb(void *p) + acb->end = (acb->nb_sectors * SECTOR_SIZE); + + state->buf_off = 0; +- if (state->orig_buf) +- g_free(state->orig_buf); ++ g_free(state->orig_buf); + state->buf_start = start; + state->buf_len = acb->end + s->readahead_size; + end = MIN(start + state->buf_len, s->len) - 1; +diff --git a/block/iscsi.c b/block/iscsi.c +index 2a4ab22..92dc1dd 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1516,9 +1516,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, + + out: + qemu_opts_del(opts); +- if (initiator_name != NULL) { +- g_free(initiator_name); +- } ++ g_free(initiator_name); + if (iscsi_url != NULL) { + iscsi_destroy_url(iscsi_url); + } +diff --git a/hw/block/onenand.c b/hw/block/onenand.c +index 8b511a7..55768ec 100644 +--- a/hw/block/onenand.c ++++ b/hw/block/onenand.c +@@ -329,9 +329,7 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn, + dp, 1) < 0; + } + } +- if (dp) { +- g_free(dp); +- } ++ g_free(dp); + } + return result; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-NULL-deference-for-unaligned-write-if-qiov.patch b/SOURCES/kvm-block-Fix-NULL-deference-for-unaligned-write-if-qiov.patch new file mode 100644 index 0000000..b46c021 --- /dev/null +++ b/SOURCES/kvm-block-Fix-NULL-deference-for-unaligned-write-if-qiov.patch @@ -0,0 +1,174 @@ +From 22db646a6d358e08c4c11f12e3dcf96f25525bf8 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 25 May 2015 04:45:56 +0200 +Subject: [PATCH 4/6] block: Fix NULL deference for unaligned write if qiov is + NULL + +Message-id: <1432529157-20381-3-git-send-email-famz@redhat.com> +Patchwork-id: 65120 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2 2/3] block: Fix NULL deference for unaligned write if qiov is NULL +Bugzilla: 1200295 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi + +For zero write, callers pass in NULL qiov (qemu-io "write -z" or +scsi-disk "write same"). + +Commit fc3959e466 fixed bdrv_co_write_zeroes which is the common case +for this bug, but it still exists in bdrv_aio_write_zeroes. A simpler +fix would be in bdrv_co_do_pwritev which is the NULL dereference point +and covers both cases. + +So don't access it in bdrv_co_do_pwritev in this case, use three aligned +writes. + +[Initialize ret to 0 in bdrv_co_do_zero_pwritev() to avoid uninitialized +variable warning with gcc 4.9.2. +--Stefan] + +Signed-off-by: Fam Zheng +Message-id: 1431522721-3266-3-git-send-email-famz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 9eeb6dd1b27bd57eb4e3869290e87feac8e8b226) + +We don't have block/io.c in downstream, applied the change to +block.c + +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + block.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 95 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index 89ab829..45543d5 100644 +--- a/block.c ++++ b/block.c +@@ -3069,6 +3069,94 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs, + return ret; + } + ++static int coroutine_fn bdrv_co_do_zero_pwritev(BlockDriverState *bs, ++ int64_t offset, ++ unsigned int bytes, ++ BdrvRequestFlags flags, ++ BdrvTrackedRequest *req) ++{ ++ uint8_t *buf = NULL; ++ QEMUIOVector local_qiov; ++ struct iovec iov; ++ uint64_t align = MAX(BDRV_SECTOR_SIZE, bs->request_alignment); ++ unsigned int head_padding_bytes, tail_padding_bytes; ++ int ret = 0; ++ ++ head_padding_bytes = offset & (align - 1); ++ tail_padding_bytes = align - ((offset + bytes) & (align - 1)); ++ ++ ++ assert(flags & BDRV_REQ_ZERO_WRITE); ++ if (head_padding_bytes || tail_padding_bytes) { ++ buf = qemu_blockalign(bs, align); ++ iov = (struct iovec) { ++ .iov_base = buf, ++ .iov_len = align, ++ }; ++ qemu_iovec_init_external(&local_qiov, &iov, 1); ++ } ++ if (head_padding_bytes) { ++ uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes); ++ ++ /* RMW the unaligned part before head. */ ++ mark_request_serialising(req, align); ++ wait_serialising_requests(req); ++ BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_HEAD); ++ ret = bdrv_aligned_preadv(bs, req, offset & ~(align - 1), align, ++ align, &local_qiov, 0); ++ if (ret < 0) { ++ goto fail; ++ } ++ BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); ++ ++ memset(buf + head_padding_bytes, 0, zero_bytes); ++ ret = bdrv_aligned_pwritev(bs, req, offset & ~(align - 1), align, ++ &local_qiov, ++ flags & ~BDRV_REQ_ZERO_WRITE); ++ if (ret < 0) { ++ goto fail; ++ } ++ offset += zero_bytes; ++ bytes -= zero_bytes; ++ } ++ ++ assert(!bytes || (offset & (align - 1)) == 0); ++ if (bytes >= align) { ++ /* Write the aligned part in the middle. */ ++ uint64_t aligned_bytes = bytes & ~(align - 1); ++ ret = bdrv_aligned_pwritev(bs, req, offset, aligned_bytes, ++ NULL, flags); ++ if (ret < 0) { ++ goto fail; ++ } ++ bytes -= aligned_bytes; ++ offset += aligned_bytes; ++ } ++ ++ assert(!bytes || (offset & (align - 1)) == 0); ++ if (bytes) { ++ assert(align == tail_padding_bytes + bytes); ++ /* RMW the unaligned part after tail. */ ++ mark_request_serialising(req, align); ++ wait_serialising_requests(req); ++ BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_TAIL); ++ ret = bdrv_aligned_preadv(bs, req, offset, align, ++ align, &local_qiov, 0); ++ if (ret < 0) { ++ goto fail; ++ } ++ BLKDBG_EVENT(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); ++ ++ memset(buf, 0, bytes); ++ ret = bdrv_aligned_pwritev(bs, req, offset, align, ++ &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE); ++ } ++fail: ++ qemu_vfree(buf); ++ return ret; ++ ++} ++ + /* + * Handle a write request in coroutine context + */ +@@ -3108,6 +3196,11 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, + */ + tracked_request_begin(&req, bs, offset, bytes, true); + ++ if (!qiov) { ++ ret = bdrv_co_do_zero_pwritev(bs, offset, bytes, flags, &req); ++ goto out; ++ } ++ + if (offset & (align - 1)) { + QEMUIOVector head_qiov; + struct iovec head_iov; +@@ -3181,14 +3274,14 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, + flags); + + fail: +- tracked_request_end(&req); + + if (use_local_qiov) { + qemu_iovec_destroy(&local_qiov); + } + qemu_vfree(head_buf); + qemu_vfree(tail_buf); +- ++out: ++ tracked_request_end(&req); + return ret; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Introduce-qemu_try_blockalign.patch b/SOURCES/kvm-block-Introduce-qemu_try_blockalign.patch new file mode 100644 index 0000000..37461a7 --- /dev/null +++ b/SOURCES/kvm-block-Introduce-qemu_try_blockalign.patch @@ -0,0 +1,156 @@ +From 90fad0c40a1947e229fdf82a30219e33a3e1dad8 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:21:57 +0200 +Subject: [PATCH 03/42] block: Introduce qemu_try_blockalign() + +Message-id: <1434212556-3927-4-git-send-email-mreitz@redhat.com> +Patchwork-id: 66022 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 03/42] block: Introduce qemu_try_blockalign() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +This function returns NULL instead of aborting when an allocation fails. + +Signed-off-by: Kevin Wolf +Reviewed-by: Benoit Canet +(cherry picked from commit 7d2a35cc921ea4832083a7e8598461868bb538ce) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block.c | 13 +++++++++++++ + include/block/block.h | 1 + + include/qemu/osdep.h | 1 + + util/oslib-posix.c | 16 ++++++++++------ + util/oslib-win32.c | 9 +++++++-- + 5 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/block.c b/block.c +index f2caf20..caea2ea 100644 +--- a/block.c ++++ b/block.c +@@ -5175,6 +5175,19 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size) + return qemu_memalign(bdrv_opt_mem_align(bs), size); + } + ++void *qemu_try_blockalign(BlockDriverState *bs, size_t size) ++{ ++ size_t align = bdrv_opt_mem_align(bs); ++ ++ /* Ensure that NULL is never returned on success */ ++ assert(align > 0); ++ if (size == 0) { ++ size = align; ++ } ++ ++ return qemu_try_memalign(align, size); ++} ++ + /* + * Check if all memory in this vector is sector aligned. + */ +diff --git a/include/block/block.h b/include/block/block.h +index 3170cbc..7b538b7 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -417,6 +417,7 @@ void bdrv_img_create(const char *filename, const char *fmt, + size_t bdrv_opt_mem_align(BlockDriverState *bs); + void bdrv_set_guest_block_size(BlockDriverState *bs, int align); + void *qemu_blockalign(BlockDriverState *bs, size_t size); ++void *qemu_try_blockalign(BlockDriverState *bs, size_t size); + bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); + + struct HBitmapIter; +diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h +index 7a5ae28..8984da0 100644 +--- a/include/qemu/osdep.h ++++ b/include/qemu/osdep.h +@@ -95,6 +95,7 @@ typedef signed int int_fast16_t; + #define qemu_printf printf + + int qemu_daemon(int nochdir, int noclose); ++void *qemu_try_memalign(size_t alignment, size_t size); + void *qemu_memalign(size_t alignment, size_t size); + void *qemu_anon_ram_alloc(size_t size); + void qemu_vfree(void *ptr); +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index fef840a..f0fb297 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -83,7 +83,7 @@ void *qemu_oom_check(void *ptr) + return ptr; + } + +-void *qemu_memalign(size_t alignment, size_t size) ++void *qemu_try_memalign(size_t alignment, size_t size) + { + void *ptr; + +@@ -95,19 +95,23 @@ void *qemu_memalign(size_t alignment, size_t size) + int ret; + ret = posix_memalign(&ptr, alignment, size); + if (ret != 0) { +- fprintf(stderr, "Failed to allocate %zu B: %s\n", +- size, strerror(ret)); +- abort(); ++ errno = ret; ++ ptr = NULL; + } + #elif defined(CONFIG_BSD) +- ptr = qemu_oom_check(valloc(size)); ++ ptr = valloc(size); + #else +- ptr = qemu_oom_check(memalign(alignment, size)); ++ ptr = memalign(alignment, size); + #endif + trace_qemu_memalign(alignment, size, ptr); + return ptr; + } + ++void *qemu_memalign(size_t alignment, size_t size) ++{ ++ return qemu_oom_check(qemu_try_memalign(alignment, size)); ++} ++ + /* alloc shared memory pages */ + void *qemu_anon_ram_alloc(size_t size) + { +diff --git a/util/oslib-win32.c b/util/oslib-win32.c +index 332e743..0fb78ef 100644 +--- a/util/oslib-win32.c ++++ b/util/oslib-win32.c +@@ -46,18 +46,23 @@ void *qemu_oom_check(void *ptr) + return ptr; + } + +-void *qemu_memalign(size_t alignment, size_t size) ++void *qemu_try_memalign(size_t alignment, size_t size) + { + void *ptr; + + if (!size) { + abort(); + } +- ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); ++ ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + trace_qemu_memalign(alignment, size, ptr); + return ptr; + } + ++void *qemu_memalign(size_t alignment, size_t size) ++{ ++ return qemu_oom_check(qemu_try_memalign(alignment, size)); ++} ++ + void *qemu_anon_ram_alloc(size_t size) + { + void *ptr; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Print-its-file-name-if-backing-file-opening-fa.patch b/SOURCES/kvm-block-Print-its-file-name-if-backing-file-opening-fa.patch new file mode 100644 index 0000000..9d0ff66 --- /dev/null +++ b/SOURCES/kvm-block-Print-its-file-name-if-backing-file-opening-fa.patch @@ -0,0 +1,172 @@ +From 82023923707c148ddd91eb3ac18fc9befc4288d5 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 22 Jul 2015 16:24:55 +0200 +Subject: [PATCH 3/5] block: Print its file name if backing file opening failed + +Message-id: <1437582297-9244-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 67106 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/3] block: Print its file name if backing file opening failed +Bugzilla: 1238639 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng + +From: Fam Zheng + +If backing file doesn't exist, the error message is confusing and +misleading: + + $ qemu /tmp/a.qcow2 + qemu: could not open disk image /tmp/a.qcow2: Could not open file: No + such file or directory + +But... + + $ ls /tmp/a.qcow2 + /tmp/a.qcow2 + + $ qemu-img info /tmp/a.qcow2 + image: /tmp/a.qcow2 + file format: qcow2 + virtual size: 8.0G (8589934592 bytes) + disk size: 196K + cluster_size: 65536 + backing file: /tmp/b.qcow2 + +Because... + + $ ls /tmp/b.qcow2 + ls: cannot access /tmp/b.qcow2: No such file or directory + +This is not intuitive. It's better to have the missing file's name in +the error message. With this patch: + + $ qemu-io -c 'read 0 512' /tmp/a.qcow2 + qemu-io: can't open device /tmp/a.qcow2: Could not open backing + file: Could not open '/stor/vm/arch.raw': No such file or directory + no file open, try 'help open' + +Which is a little bit better. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit b04b6b6ec3a1e0ba90c2f58617286d9fc35fa372) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/082.out + tests/qemu-iotests/114.out + +When both tests were introduced downstream +(6b1816a687831a1622637ed10605759d9e90aa9c and +a0f50f0877463e9370ffa411bd826d7c704ab9fe, respectively), they were +modified from upstream because this patch had not been backported. These +changes are now reverted. + +Signed-off-by: Max Reitz +--- + block.c | 4 +++- + block/raw-posix.c | 1 - + block/raw-win32.c | 1 - + tests/qemu-iotests/051.out | 2 +- + tests/qemu-iotests/069.out | 2 +- + tests/qemu-iotests/082.out | 4 ++-- + tests/qemu-iotests/114.out | 2 +- + 7 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/block.c b/block.c +index e36fa2f..dedfa52 100644 +--- a/block.c ++++ b/block.c +@@ -1050,7 +1050,9 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + bdrv_unref(bs->backing_hd); + bs->backing_hd = NULL; + bs->open_flags |= BDRV_O_NO_BACKING; +- error_propagate(errp, local_err); ++ error_setg(errp, "Could not open backing file: %s", ++ error_get_pretty(local_err)); ++ error_free(local_err); + return ret; + } + +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 46b941b..72a9dc0 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -388,7 +388,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + if (ret == -EROFS) { + ret = -EACCES; + } +- error_setg_errno(errp, -ret, "Could not open file"); + goto fail; + } + s->fd = fd; +diff --git a/block/raw-win32.c b/block/raw-win32.c +index ac20370..bb6dc6a 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -319,7 +319,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + } else { + ret = -EINVAL; + } +- error_setg_errno(errp, -ret, "Could not open file"); + goto fail; + } + +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 4fca1ca..32c94e5 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -169,6 +169,6 @@ Testing: -drive file=foo:bar + QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: Unknown protocol + + Testing: -drive file.filename=foo:bar +-QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open file: No such file or directory ++QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open 'foo:bar': No such file or directory + + *** done +diff --git a/tests/qemu-iotests/069.out b/tests/qemu-iotests/069.out +index 3648814..b48306d 100644 +--- a/tests/qemu-iotests/069.out ++++ b/tests/qemu-iotests/069.out +@@ -4,5 +4,5 @@ QA output created by 069 + + Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base' +-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open file: No such file or directory ++qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory + *** done +diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out +index 8abfde7..41324d5 100644 +--- a/tests/qemu-iotests/082.out ++++ b/tests/qemu-iotests/082.out +@@ -326,10 +326,10 @@ preallocation Preallocation mode (allowed values: off, metadata, falloc, full + lazy_refcounts Postpone refcount updates + + Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base +-qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open file: No such file or directory ++qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory + + Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base +-qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open file: No such file or directory ++qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,?': No such file or directory + + Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base + qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2, +diff --git a/tests/qemu-iotests/114.out b/tests/qemu-iotests/114.out +index de8f529..6c6b210 100644 +--- a/tests/qemu-iotests/114.out ++++ b/tests/qemu-iotests/114.out +@@ -7,7 +7,7 @@ virtual size: 64M (67108864 bytes) + cluster_size: 65536 + backing file: TEST_DIR/t.IMGFMT.base + backing file format: foo +-qemu-io: can't open device TEST_DIR/t.qcow2: Unknown driver 'foo' ++qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo' + read 4096/4096 bytes at offset 0 + 4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Propagate-error-in-bdrv_img_create.patch b/SOURCES/kvm-block-Propagate-error-in-bdrv_img_create.patch new file mode 100644 index 0000000..496abf1 --- /dev/null +++ b/SOURCES/kvm-block-Propagate-error-in-bdrv_img_create.patch @@ -0,0 +1,55 @@ +From 3b439999998f800a1a09d6bb779e9f3eef4f1eb9 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 22 Jul 2015 16:24:56 +0200 +Subject: [PATCH 4/5] block: Propagate error in bdrv_img_create() + +Message-id: <1437582297-9244-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 67107 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/3] block: Propagate error in bdrv_img_create() +Bugzilla: 1238639 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng + +If the specified backing file could not be opened, do not generate a new +error message which contains the message which has been generated by +bdrv_open(), but just propagate the latter. + +Signed-off-by: Max Reitz +Reviewed-by: Kevin Wolf +Reviewed-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit e56934becea70817124be1534f4289ce7d8f6733) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block.c + +A conflict in the code being removed due to +83d0521a1e35989b0cb7235aef48455fedda3ca4 missing downstream. + +Signed-off-by: Max Reitz +--- + block.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/block.c b/block.c +index dedfa52..bc6e75c 100644 +--- a/block.c ++++ b/block.c +@@ -5489,11 +5489,6 @@ void bdrv_img_create(const char *filename, const char *fmt, + ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags, + backing_drv, &local_err); + if (ret < 0) { +- error_setg_errno(errp, -ret, "Could not open '%s': %s", +- backing_file->value.s, +- error_get_pretty(local_err)); +- error_free(local_err); +- local_err = NULL; + goto out; + } + bdrv_get_geometry(bs, &size); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Respect-underlying-file-s-EOF.patch b/SOURCES/kvm-block-Respect-underlying-file-s-EOF.patch new file mode 100644 index 0000000..0a8edf2 --- /dev/null +++ b/SOURCES/kvm-block-Respect-underlying-file-s-EOF.patch @@ -0,0 +1,65 @@ +From 69fe324e32aad7e1afc6ad14021a6a08ad52646c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:27 +0200 +Subject: [PATCH 33/42] block: Respect underlying file's EOF + +Message-id: <1434212556-3927-34-git-send-email-mreitz@redhat.com> +Patchwork-id: 66052 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 33/42] block: Respect underlying file's EOF +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +When falling through to the underlying file in +bdrv_co_get_block_status(), if it returns that the query offset is +beyond the file end (by setting *pnum to 0), return the range to be +zero and do not let the number of sectors for which information could be +obtained be overwritten. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 59c9a95fd29cfb3296ee58e8a446df251d14a459) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index 22ab762..fa6e192 100644 +--- a/block.c ++++ b/block.c +@@ -3797,13 +3797,24 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + if (bs->file && + (ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) && + (ret & BDRV_BLOCK_OFFSET_VALID)) { ++ int file_pnum; ++ + ret2 = bdrv_co_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS, +- *pnum, pnum); ++ *pnum, &file_pnum); + if (ret2 >= 0) { + /* Ignore errors. This is just providing extra information, it + * is useful but not necessary. + */ +- ret |= (ret2 & BDRV_BLOCK_ZERO); ++ if (!file_pnum) { ++ /* !file_pnum indicates an offset at or beyond the EOF; it is ++ * perfectly valid for the format block driver to point to such ++ * offsets, so catch it and mark everything as zero */ ++ ret |= BDRV_BLOCK_ZERO; ++ } else { ++ /* Limit request to the range reported by the protocol driver */ ++ *pnum = file_pnum; ++ ret |= (ret2 & BDRV_BLOCK_ZERO); ++ } + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-coverity-fix-check-return-value-for-fcntl-in-g.patch b/SOURCES/kvm-block-coverity-fix-check-return-value-for-fcntl-in-g.patch new file mode 100644 index 0000000..05df3e8 --- /dev/null +++ b/SOURCES/kvm-block-coverity-fix-check-return-value-for-fcntl-in-g.patch @@ -0,0 +1,51 @@ +From 25730930b496dd639afe8906744ce9ebeb7db7e9 Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Wed, 5 Aug 2015 14:38:26 +0200 +Subject: [PATCH 3/3] block: coverity fix: check return value for fcntl in + gluster + +Message-id: <9a482772dc4e110d2a774bbed0e1dbecdaaec43e.1438784597.git.jcody@redhat.com> +Patchwork-id: 67323 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v3] block: coverity fix: check return value for fcntl in gluster +Bugzilla: 1219217 +RH-Acked-by: Max Reitz +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +Check return value in the Gluster driver for fcntl, as pointed +out by coverity. + +Cleanup of s->fds is done inline in the error handling for the fcntl() +call, rather than in the function cleanup, to keep changes minimal for +future backports. + +Downstream-only, as upstream Gluster driver does not use fcntl anymore. + +Signed-off-by: Jeff Cody +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/block/gluster.c b/block/gluster.c +index 5f85799..1793386 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -357,7 +357,13 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options, + ret = -errno; + goto out; + } +- fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK); ++ ret = fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK); ++ if (ret < 0) { ++ ret = -errno; ++ close(s->fds[GLUSTER_FD_READ]); ++ close(s->fds[GLUSTER_FD_WRITE]); ++ goto out; ++ } + qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], + qemu_gluster_aio_event_reader, NULL, qemu_gluster_aio_flush_cb, s); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-curl-Don-t-lose-original-error-when-a-connecti.patch b/SOURCES/kvm-block-curl-Don-t-lose-original-error-when-a-connecti.patch new file mode 100644 index 0000000..c3f5589 --- /dev/null +++ b/SOURCES/kvm-block-curl-Don-t-lose-original-error-when-a-connecti.patch @@ -0,0 +1,100 @@ +From 264a2066904d31c46860e0bac8790d57e6498b80 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 16 Jul 2015 15:41:54 +0200 +Subject: [PATCH 1/5] block/curl: Don't lose original error when a connection + fails. + +Message-id: <1437061314-4775-1-git-send-email-rjones@redhat.com> +Patchwork-id: 67043 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v3] block/curl: Don't lose original error when a connection fails. +Bugzilla: 1235812 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Stefan Hajnoczi + +From: "Richard W.M. Jones" + +Currently if qemu is connected to a curl source (eg. web server), and +the web server fails / times out / dies, you always see a bogus EIO +"Input/output error". + +For example, choose a large file located on any local webserver which +you control: + + $ qemu-img convert -p http://example.com/large.iso /tmp/test + +Once it starts copying the file, stop the webserver and you will see +qemu-img fail with: + + qemu-img: error while reading sector 61440: Input/output error + +This patch does two things: Firstly print the actual error from curl +so it doesn't get lost. Secondly, change EIO to EPROTO. EPROTO is a +POSIX.1 compatible errno which more accurately reflects that there was +a protocol error, rather than some kind of hardware failure. + +After this patch is applied, the error changes to: + + $ qemu-img convert -p http://example.com/large.iso /tmp/test + qemu-img: curl: transfer closed with 469989 bytes remaining to read + qemu-img: error while reading sector 16384: Protocol error + +Signed-off-by: Richard W.M. Jones +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Jeff Cody + +BZ: https://bugzilla.redhat.com/1235812 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=9529354 +Upstream-status: 796a060bc0fab40953997976a2e30d9d6235bc7b +--- + block/curl.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index 3088329..dfa8cee 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -22,6 +22,7 @@ + * THE SOFTWARE. + */ + #include "qemu-common.h" ++#include "qemu/error-report.h" + #include "block/block_int.h" + #include "qapi/qmp/qbool.h" + #include +@@ -294,6 +295,18 @@ static void curl_multi_check_completion(BDRVCURLState *s) + /* ACBs for successful messages get completed in curl_read_cb */ + if (msg->data.result != CURLE_OK) { + int i; ++ static int errcount = 100; ++ ++ /* Don't lose the original error message from curl, since ++ * it contains extra data. ++ */ ++ if (errcount > 0) { ++ error_report("curl: %s", state->errmsg); ++ if (--errcount == 0) { ++ error_report("curl: further errors suppressed"); ++ } ++ } ++ + for (i = 0; i < CURL_NUM_ACB; i++) { + CURLAIOCB *acb = state->acb[i]; + +@@ -301,7 +314,7 @@ static void curl_multi_check_completion(BDRVCURLState *s) + continue; + } + +- acb->common.cb(acb->common.opaque, -EIO); ++ acb->common.cb(acb->common.opaque, -EPROTO); + qemu_aio_release(acb); + state->acb[i] = NULL; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-curl-Implement-the-libcurl-timer-callback-inte.patch b/SOURCES/kvm-block-curl-Implement-the-libcurl-timer-callback-inte.patch new file mode 100644 index 0000000..57d6b49 --- /dev/null +++ b/SOURCES/kvm-block-curl-Implement-the-libcurl-timer-callback-inte.patch @@ -0,0 +1,200 @@ +From a8b59fd3d7aa9f6a16caf4c13534039a81552118 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:14 +0200 +Subject: [PATCH 14/30] block/curl: Implement the libcurl timer callback + interface + +Message-id: <1434022828-13037-8-git-send-email-rjones@redhat.com> +Patchwork-id: 65842 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 07/21] block/curl: Implement the libcurl timer callback interface +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Peter Maydell + +libcurl versions 7.16.0 and later have a timer callback interface which +must be implemented in order for libcurl to make forward progress (it +will sometimes rely on being called back on the timeout if there are +no file descriptors registered). Implement the callback, and use a +QEMU AIO timer to ensure we prod libcurl again when it asks us to. + +Based on Peter's original patch plus my fix to add curl_multi_timeout_do. +Should compile just fine even on older versions of libcurl. + +I also tried copy-on-read and streaming: + + $ ./qemu-img create -f qcow2 -o \ + backing_file=http://download.fedoraproject.org/pub/fedora/linux/releases/20/Live/x86_64/Fedora-Live-Desktop-x86_64-20-1.iso \ + foo.qcow2 1G + $ x86_64-softmmu/qemu-system-x86_64 \ + -drive if=none,file=foo.qcow2,copy-on-read=on,id=cd \ + -device ide-cd,drive=cd --enable-kvm -m 1024 + +Direct http usage is probably too slow, but with copy-on-read ultimately +the image does boot! + +After some time, streaming gets canceled by an EIO, which needs further +investigation. + +Signed-off-by: Peter Maydell +Signed-off-by: Paolo Bonzini +Signed-off-by: Kevin Wolf + +Upstream-status: 031fd1be5618c347f9aeb44ec294f14a541e42b2 + +This patch is modified from upstream by adapting the patch +to use the timers API from qemu 1.5.3. (Thanks: Kevin Wolf) + +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 70 insertions(+), 11 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 7569dd5..a6631fe 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -34,6 +34,11 @@ + #define DPRINTF(fmt, ...) do { } while (0) + #endif + ++#if LIBCURL_VERSION_NUM >= 0x071000 ++/* The multi interface timer callback was introduced in 7.16.0 */ ++#define NEED_CURL_TIMER_CALLBACK ++#endif ++ + #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ + CURLPROTO_FTP | CURLPROTO_FTPS | \ + CURLPROTO_TFTP) +@@ -77,6 +82,7 @@ typedef struct CURLState + + typedef struct BDRVCURLState { + CURLM *multi; ++ QEMUTimer *timer; + size_t len; + CURLState states[CURL_NUM_STATES]; + char *url; +@@ -87,6 +93,23 @@ static void curl_clean_state(CURLState *s); + static void curl_multi_do(void *arg); + static int curl_aio_flush(void *opaque); + ++#ifdef NEED_CURL_TIMER_CALLBACK ++static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) ++{ ++ BDRVCURLState *s = opaque; ++ ++ DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms); ++ if (timeout_ms == -1) { ++ qemu_del_timer(s->timer); ++ } else { ++ int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000; ++ qemu_mod_timer(s->timer, ++ qemu_get_clock_ns(rt_clock) + timeout_ns); ++ } ++ return 0; ++} ++#endif ++ + static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + void *s, void *sp) + { +@@ -213,20 +236,10 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, + return FIND_RET_NONE; + } + +-static void curl_multi_do(void *arg) ++static void curl_multi_read(BDRVCURLState *s) + { +- BDRVCURLState *s = (BDRVCURLState *)arg; +- int running; +- int r; + int msgs_in_queue; + +- if (!s->multi) +- return; +- +- do { +- r = curl_multi_socket_all(s->multi, &running); +- } while(r == CURLM_CALL_MULTI_PERFORM); +- + /* Try to find done transfers, so we can free the easy + * handle again. */ + do { +@@ -271,6 +284,41 @@ static void curl_multi_do(void *arg) + } while(msgs_in_queue); + } + ++static void curl_multi_do(void *arg) ++{ ++ BDRVCURLState *s = (BDRVCURLState *)arg; ++ int running; ++ int r; ++ ++ if (!s->multi) { ++ return; ++ } ++ ++ do { ++ r = curl_multi_socket_all(s->multi, &running); ++ } while(r == CURLM_CALL_MULTI_PERFORM); ++ ++ curl_multi_read(s); ++} ++ ++static void curl_multi_timeout_do(void *arg) ++{ ++#ifdef NEED_CURL_TIMER_CALLBACK ++ BDRVCURLState *s = (BDRVCURLState *)arg; ++ int running; ++ ++ if (!s->multi) { ++ return; ++ } ++ ++ curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); ++ ++ curl_multi_read(s); ++#else ++ abort(); ++#endif ++} ++ + static CURLState *curl_init_state(BDRVCURLState *s) + { + CURLState *state = NULL; +@@ -462,12 +510,19 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + curl_easy_cleanup(state->curl); + state->curl = NULL; + ++ s->timer = qemu_new_timer(rt_clock, SCALE_NS, ++ curl_multi_timeout_do, s); ++ + // Now we know the file exists and its size, so let's + // initialize the multi interface! + + s->multi = curl_multi_init(); + curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); + curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); ++#ifdef NEED_CURL_TIMER_CALLBACK ++ curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); ++ curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); ++#endif + curl_multi_do(s); + + qemu_opts_del(opts); +@@ -607,6 +662,10 @@ static void curl_close(BlockDriverState *bs) + } + if (s->multi) + curl_multi_cleanup(s->multi); ++ ++ qemu_del_timer(s->timer); ++ qemu_free_timer(s->timer); ++ + g_free(s->url); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-curl-Improve-type-safety-of-s-timeout.patch b/SOURCES/kvm-block-curl-Improve-type-safety-of-s-timeout.patch new file mode 100644 index 0000000..c4d38b3 --- /dev/null +++ b/SOURCES/kvm-block-curl-Improve-type-safety-of-s-timeout.patch @@ -0,0 +1,88 @@ +From c44c930396e5c19511f36bc45c3f386966b15f9d Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:28 +0200 +Subject: [PATCH 28/30] block/curl: Improve type safety of s->timeout. + +Message-id: <1434022828-13037-22-git-send-email-rjones@redhat.com> +Patchwork-id: 65856 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 21/21] block/curl: Improve type safety of s->timeout. +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: "Richard W.M. Jones" + +qemu_opt_get_number returns a uint64_t, and curl_easy_setopt expects a +long (not an int). There is no warning about the latter type error +because curl_easy_setopt uses a varargs argument. + +Store the timeout (which is a positive number of seconds) as a +uint64_t. Check that the number given by the user is reasonable. +Zero is permissible (meaning no timeout is enforced by cURL). + +Cast it to long before calling curl_easy_setopt to fix the type error. + +Example error message after this change has been applied: + +$ ./qemu-img create -f qcow2 /tmp/test.qcow2 \ + -b 'json: { "file.driver":"https", + "file.url":"https://foo/bar", + "file.timeout":-1 }' +qemu-img: /tmp/test.qcow2: Could not open 'json: { "file.driver":"https", "file.url":"https://foo/bar", "file.timeout":-1 }': timeout parameter is too large or negative: Invalid argument + +Signed-off-by: Richard W.M. Jones +Reviewed-by: Laszlo Ersek +Reviewed-by: Gonglei +Signed-off-by: Stefan Hajnoczi + +Upstream-status: f76faeda4bd59f972d09dd9d954297f17c21dd60 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 5b407aa..3088329 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -64,6 +64,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define SECTOR_SIZE 512 + #define READ_AHEAD_DEFAULT (256 * 1024) + #define CURL_TIMEOUT_DEFAULT 5 ++#define CURL_TIMEOUT_MAX 10000 + + #define FIND_RET_NONE 0 + #define FIND_RET_OK 1 +@@ -112,7 +113,7 @@ typedef struct BDRVCURLState { + char *url; + size_t readahead_size; + bool sslverify; +- int timeout; ++ uint64_t timeout; + char *cookie; + bool accept_range; + } BDRVCURLState; +@@ -387,7 +388,7 @@ static CURLState *curl_init_state(BDRVCURLState *s) + if (s->cookie) { + curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie); + } +- curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, s->timeout); ++ curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout); + curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, + (void *)curl_read_cb); + curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); +@@ -496,6 +497,10 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + + s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, + CURL_TIMEOUT_DEFAULT); ++ if (s->timeout > CURL_TIMEOUT_MAX) { ++ error_setg(errp, "timeout parameter is too large or negative"); ++ goto out_noclean; ++ } + + s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-qemu-iotests-add-check-for-multiplication-over.patch b/SOURCES/kvm-block-qemu-iotests-add-check-for-multiplication-over.patch new file mode 100644 index 0000000..e626c9b --- /dev/null +++ b/SOURCES/kvm-block-qemu-iotests-add-check-for-multiplication-over.patch @@ -0,0 +1,121 @@ +From 119ce531952beab96a8b807721e2180d99382073 Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Wed, 29 Jul 2015 16:59:55 +0200 +Subject: [PATCH 04/13] block: qemu-iotests - add check for multiplication + overflow in vpc + +Message-id: <9e859f3912d1852e48fb7e25a3679bd74500c36d.1438188988.git.jcody@redhat.com> +Patchwork-id: 67198 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/3] block: qemu-iotests - add check for multiplication overflow in vpc +Bugzilla: 1217349 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +This checks that VPC is able to successfully fail (without segfault) +on an image file with a max_table_entries that exceeds 0x40000000. + +This table entry is within the valid range for VPC (although too large +for this sample image). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Jeff Cody +Signed-off-by: Kevin Wolf +(cherry picked from commit 77c102c26ead946fe7589d4bddcdfa5cb431ebfe) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Jeff Cody +--- + tests/qemu-iotests/135 | 54 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/135.out | 5 +++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 60 insertions(+) + create mode 100755 tests/qemu-iotests/135 + create mode 100644 tests/qemu-iotests/135.out + +diff --git a/tests/qemu-iotests/135 b/tests/qemu-iotests/135 +new file mode 100755 +index 0000000..16bf736 +--- /dev/null ++++ b/tests/qemu-iotests/135 +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test VPC open of image with large Max Table Entries value. ++# ++# Copyright (C) 2015 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=jcody@redhat.com ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++here=`pwd` ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt vpc ++_supported_proto generic ++_supported_os Linux ++ ++_use_sample_img afl5.img.bz2 ++ ++echo ++echo "=== Verify image open and failure ====" ++$QEMU_IMG info "$TEST_IMG" 2>&1| _filter_testdir ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/135.out b/tests/qemu-iotests/135.out +new file mode 100644 +index 0000000..793898b +--- /dev/null ++++ b/tests/qemu-iotests/135.out +@@ -0,0 +1,5 @@ ++QA output created by 135 ++ ++=== Verify image open and failure ==== ++qemu-img: Could not open 'TEST_DIR/afl5.img': Max Table Entries too large (1073741825) ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 0644c42..58b3d05 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -92,3 +92,4 @@ + 114 rw auto quick + 121 rw auto + 130 rw auto quick ++135 rw auto +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Drop-superfluous-libssh2_session_last_errn.patch b/SOURCES/kvm-block-ssh-Drop-superfluous-libssh2_session_last_errn.patch new file mode 100644 index 0000000..1d5ad07 --- /dev/null +++ b/SOURCES/kvm-block-ssh-Drop-superfluous-libssh2_session_last_errn.patch @@ -0,0 +1,60 @@ +From 8d385a8bc9d20d1c0ec09579f14a98294b448985 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:56:55 +0200 +Subject: [PATCH 02/30] block/ssh: Drop superfluous + libssh2_session_last_errno() calls + +Message-id: <1433764620-20506-2-git-send-email-rjones@redhat.com> +Patchwork-id: 65477 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/6] block/ssh: Drop superfluous libssh2_session_last_errno() calls +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +libssh2_session_last_error() already returns the error code. + +Signed-off-by: Markus Armbruster +Reviewed-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 04bc7c0e38fc77afc116031f1e25af80374b1971 +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index fa3c78d..1f7c6ed 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -121,10 +121,9 @@ session_error_report(BDRVSSHState *s, const char *fs, ...) + char *ssh_err; + int ssh_err_code; + +- libssh2_session_last_error((s)->session, &ssh_err, NULL, 0); + /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_errno((s)->session); +- ++ ssh_err_code = libssh2_session_last_error(s->session, ++ &ssh_err, NULL, 0); + error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code); + } + +@@ -145,9 +144,9 @@ sftp_error_report(BDRVSSHState *s, const char *fs, ...) + int ssh_err_code; + unsigned long sftp_err_code; + +- libssh2_session_last_error((s)->session, &ssh_err, NULL, 0); + /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_errno((s)->session); ++ ssh_err_code = libssh2_session_last_error(s->session, ++ &ssh_err, NULL, 0); + /* See . */ + sftp_err_code = libssh2_sftp_last_error((s)->sftp); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Propagate-errors-through-authenticate.patch b/SOURCES/kvm-block-ssh-Propagate-errors-through-authenticate.patch new file mode 100644 index 0000000..e6d2e56 --- /dev/null +++ b/SOURCES/kvm-block-ssh-Propagate-errors-through-authenticate.patch @@ -0,0 +1,106 @@ +From aa59c26b76954860b4c7f7e57d1d4b8b99ccfa6f Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:56:57 +0200 +Subject: [PATCH 04/30] block/ssh: Propagate errors through authenticate() + +Message-id: <1433764620-20506-4-git-send-email-rjones@redhat.com> +Patchwork-id: 65478 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/6] block/ssh: Propagate errors through authenticate() +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 4618e658e6dadd1ba53585157984eac71cb706c6 +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 6ffcff1..5908e6d 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -434,7 +434,7 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + return -EINVAL; + } + +-static int authenticate(BDRVSSHState *s, const char *user) ++static int authenticate(BDRVSSHState *s, const char *user, Error **errp) + { + int r, ret; + const char *userauthlist; +@@ -445,7 +445,8 @@ static int authenticate(BDRVSSHState *s, const char *user) + userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); + if (strstr(userauthlist, "publickey") == NULL) { + ret = -EPERM; +- error_report("remote server does not support \"publickey\" authentication"); ++ error_setg(errp, ++ "remote server does not support \"publickey\" authentication"); + goto out; + } + +@@ -453,17 +454,18 @@ static int authenticate(BDRVSSHState *s, const char *user) + agent = libssh2_agent_init(s->session); + if (!agent) { + ret = -EINVAL; +- session_error_report(s, "failed to initialize ssh-agent support"); ++ session_error_setg(errp, s, "failed to initialize ssh-agent support"); + goto out; + } + if (libssh2_agent_connect(agent)) { + ret = -ECONNREFUSED; +- session_error_report(s, "failed to connect to ssh-agent"); ++ session_error_setg(errp, s, "failed to connect to ssh-agent"); + goto out; + } + if (libssh2_agent_list_identities(agent)) { + ret = -EINVAL; +- session_error_report(s, "failed requesting identities from ssh-agent"); ++ session_error_setg(errp, s, ++ "failed requesting identities from ssh-agent"); + goto out; + } + +@@ -474,7 +476,8 @@ static int authenticate(BDRVSSHState *s, const char *user) + } + if (r < 0) { + ret = -EINVAL; +- session_error_report(s, "failed to obtain identity from ssh-agent"); ++ session_error_setg(errp, s, ++ "failed to obtain identity from ssh-agent"); + goto out; + } + r = libssh2_agent_userauth(agent, user, identity); +@@ -488,8 +491,8 @@ static int authenticate(BDRVSSHState *s, const char *user) + } + + ret = -EPERM; +- error_report("failed to authenticate using publickey authentication " +- "and the identities held by your ssh-agent"); ++ error_setg(errp, "failed to authenticate using publickey authentication " ++ "and the identities held by your ssh-agent"); + + out: + if (agent != NULL) { +@@ -577,8 +580,10 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + } + + /* Authenticate. */ +- ret = authenticate(s, user); ++ ret = authenticate(s, user, &err); + if (ret < 0) { ++ qerror_report_err(err); ++ error_free(err); + goto err; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Propagate-errors-through-check_host_key.patch b/SOURCES/kvm-block-ssh-Propagate-errors-through-check_host_key.patch new file mode 100644 index 0000000..d3c7f2f --- /dev/null +++ b/SOURCES/kvm-block-ssh-Propagate-errors-through-check_host_key.patch @@ -0,0 +1,193 @@ +From 6151164b6f33870c511a7f5f0f64356bb8fe2ff2 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:56:56 +0200 +Subject: [PATCH 03/30] block/ssh: Propagate errors through check_host_key() + +Message-id: <1433764620-20506-3-git-send-email-rjones@redhat.com> +Patchwork-id: 65479 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/6] block/ssh: Propagate errors through check_host_key() +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 01c2b265fce921d6460e06f5af4dfb405119cbab +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 68 ++++++++++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 49 insertions(+), 19 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 1f7c6ed..6ffcff1 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -106,6 +106,31 @@ static void ssh_state_free(BDRVSSHState *s) + } + } + ++static void GCC_FMT_ATTR(3, 4) ++session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) ++{ ++ va_list args; ++ char *msg; ++ ++ va_start(args, fs); ++ msg = g_strdup_vprintf(fs, args); ++ va_end(args); ++ ++ if (s->session) { ++ char *ssh_err; ++ int ssh_err_code; ++ ++ /* This is not an errno. See . */ ++ ssh_err_code = libssh2_session_last_error(s->session, ++ &ssh_err, NULL, 0); ++ error_setg(errp, "%s: %s (libssh2 error code: %d)", ++ msg, ssh_err, ssh_err_code); ++ } else { ++ error_setg(errp, "%s", msg); ++ } ++ g_free(msg); ++} ++ + /* Wrappers around error_report which make sure to dump as much + * information from libssh2 as possible. + */ +@@ -242,7 +267,7 @@ static void ssh_parse_filename(const char *filename, QDict *options, + } + + static int check_host_key_knownhosts(BDRVSSHState *s, +- const char *host, int port) ++ const char *host, int port, Error **errp) + { + const char *home; + char *knh_file = NULL; +@@ -256,14 +281,15 @@ static int check_host_key_knownhosts(BDRVSSHState *s, + hostkey = libssh2_session_hostkey(s->session, &len, &type); + if (!hostkey) { + ret = -EINVAL; +- session_error_report(s, "failed to read remote host key"); ++ session_error_setg(errp, s, "failed to read remote host key"); + goto out; + } + + knh = libssh2_knownhost_init(s->session); + if (!knh) { + ret = -EINVAL; +- session_error_report(s, "failed to initialize known hosts support"); ++ session_error_setg(errp, s, ++ "failed to initialize known hosts support"); + goto out; + } + +@@ -288,21 +314,23 @@ static int check_host_key_knownhosts(BDRVSSHState *s, + break; + case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: + ret = -EINVAL; +- session_error_report(s, "host key does not match the one in known_hosts (found key %s)", +- found->key); ++ session_error_setg(errp, s, ++ "host key does not match the one in known_hosts" ++ " (found key %s)", found->key); + goto out; + case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: + ret = -EINVAL; +- session_error_report(s, "no host key was found in known_hosts"); ++ session_error_setg(errp, s, "no host key was found in known_hosts"); + goto out; + case LIBSSH2_KNOWNHOST_CHECK_FAILURE: + ret = -EINVAL; +- session_error_report(s, "failure matching the host key with known_hosts"); ++ session_error_setg(errp, s, ++ "failure matching the host key with known_hosts"); + goto out; + default: + ret = -EINVAL; +- session_error_report(s, "unknown error matching the host key with known_hosts (%d)", +- r); ++ session_error_setg(errp, s, "unknown error matching the host key" ++ " with known_hosts (%d)", r); + goto out; + } + +@@ -357,20 +385,20 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len, + + static int + check_host_key_hash(BDRVSSHState *s, const char *hash, +- int hash_type, size_t fingerprint_len) ++ int hash_type, size_t fingerprint_len, Error **errp) + { + const char *fingerprint; + + fingerprint = libssh2_hostkey_hash(s->session, hash_type); + if (!fingerprint) { +- session_error_report(s, "failed to read remote host key"); ++ session_error_setg(errp, s, "failed to read remote host key"); + return -EINVAL; + } + + if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, + hash) != 0) { +- error_report("remote host key does not match host_key_check '%s'", +- hash); ++ error_setg(errp, "remote host key does not match host_key_check '%s'", ++ hash); + return -EPERM; + } + +@@ -378,7 +406,7 @@ check_host_key_hash(BDRVSSHState *s, const char *hash, + } + + static int check_host_key(BDRVSSHState *s, const char *host, int port, +- const char *host_key_check) ++ const char *host_key_check, Error **errp) + { + /* host_key_check=no */ + if (strcmp(host_key_check, "no") == 0) { +@@ -388,21 +416,21 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + /* host_key_check=md5:xx:yy:zz:... */ + if (strncmp(host_key_check, "md5:", 4) == 0) { + return check_host_key_hash(s, &host_key_check[4], +- LIBSSH2_HOSTKEY_HASH_MD5, 16); ++ LIBSSH2_HOSTKEY_HASH_MD5, 16, errp); + } + + /* host_key_check=sha1:xx:yy:zz:... */ + if (strncmp(host_key_check, "sha1:", 5) == 0) { + return check_host_key_hash(s, &host_key_check[5], +- LIBSSH2_HOSTKEY_HASH_SHA1, 20); ++ LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp); + } + + /* host_key_check=yes */ + if (strcmp(host_key_check, "yes") == 0) { +- return check_host_key_knownhosts(s, host, port); ++ return check_host_key_knownhosts(s, host, port, errp); + } + +- error_report("unknown host_key_check setting (%s)", host_key_check); ++ error_setg(errp, "unknown host_key_check setting (%s)", host_key_check); + return -EINVAL; + } + +@@ -541,8 +569,10 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + } + + /* Check the remote host's key against known_hosts. */ +- ret = check_host_key(s, host, port, host_key_check); ++ ret = check_host_key(s, host, port, host_key_check, &err); + if (ret < 0) { ++ qerror_report_err(err); ++ error_free(err); + goto err; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Propagate-errors-through-connect_to_ssh.patch b/SOURCES/kvm-block-ssh-Propagate-errors-through-connect_to_ssh.patch new file mode 100644 index 0000000..753826d --- /dev/null +++ b/SOURCES/kvm-block-ssh-Propagate-errors-through-connect_to_ssh.patch @@ -0,0 +1,143 @@ +From bd7acae27a2bc4bc1a7865fdaeb30fd9c3a0430c Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:56:58 +0200 +Subject: [PATCH 05/30] block/ssh: Propagate errors through connect_to_ssh() + +Message-id: <1433764620-20506-5-git-send-email-rjones@redhat.com> +Patchwork-id: 65480 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 4/6] block/ssh: Propagate errors through connect_to_ssh() +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 5f0c39e59822fdfd6a730824eded06209942e495 +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 5908e6d..07f8a2c 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -506,10 +506,9 @@ static int authenticate(BDRVSSHState *s, const char *user, Error **errp) + } + + static int connect_to_ssh(BDRVSSHState *s, QDict *options, +- int ssh_flags, int creat_mode) ++ int ssh_flags, int creat_mode, Error **errp) + { + int r, ret; +- Error *err = NULL; + const char *host, *user, *path, *host_key_check; + int port; + +@@ -528,6 +527,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + } else { + user = g_get_user_name(); + if (!user) { ++ error_setg_errno(errp, errno, "Can't get user name"); + ret = -errno; + goto err; + } +@@ -544,11 +544,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + s->hostport = g_strdup_printf("%s:%d", host, port); + + /* Open the socket and connect. */ +- s->sock = inet_connect(s->hostport, &err); +- if (err != NULL) { ++ s->sock = inet_connect(s->hostport, errp); ++ if (s->sock < 0) { + ret = -errno; +- qerror_report_err(err); +- error_free(err); + goto err; + } + +@@ -556,7 +554,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + s->session = libssh2_session_init(); + if (!s->session) { + ret = -EINVAL; +- session_error_report(s, "failed to initialize libssh2 session"); ++ session_error_setg(errp, s, "failed to initialize libssh2 session"); + goto err; + } + +@@ -567,30 +565,26 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + r = libssh2_session_handshake(s->session, s->sock); + if (r != 0) { + ret = -EINVAL; +- session_error_report(s, "failed to establish SSH session"); ++ session_error_setg(errp, s, "failed to establish SSH session"); + goto err; + } + + /* Check the remote host's key against known_hosts. */ +- ret = check_host_key(s, host, port, host_key_check, &err); ++ ret = check_host_key(s, host, port, host_key_check, errp); + if (ret < 0) { +- qerror_report_err(err); +- error_free(err); + goto err; + } + + /* Authenticate. */ +- ret = authenticate(s, user, &err); ++ ret = authenticate(s, user, errp); + if (ret < 0) { +- qerror_report_err(err); +- error_free(err); + goto err; + } + + /* Start SFTP. */ + s->sftp = libssh2_sftp_init(s->session); + if (!s->sftp) { +- session_error_report(s, "failed to initialize sftp handle"); ++ session_error_setg(errp, s, "failed to initialize sftp handle"); + ret = -EINVAL; + goto err; + } +@@ -645,6 +639,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + Error **errp) + { ++ Error *local_err = NULL; + BDRVSSHState *s = bs->opaque; + int ret; + int ssh_flags; +@@ -657,8 +652,10 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + } + + /* Start up SSH. */ +- ret = connect_to_ssh(s, options, ssh_flags, 0); ++ ret = connect_to_ssh(s, options, ssh_flags, 0, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto err; + } + +@@ -718,8 +715,11 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, + + r = connect_to_ssh(&s, uri_options, + LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| +- LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0644); ++ LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, ++ 0644, &local_err); + if (r < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + ret = r; + goto out; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Propagate-errors-to-open-and-create-method.patch b/SOURCES/kvm-block-ssh-Propagate-errors-to-open-and-create-method.patch new file mode 100644 index 0000000..f85344c --- /dev/null +++ b/SOURCES/kvm-block-ssh-Propagate-errors-to-open-and-create-method.patch @@ -0,0 +1,158 @@ +From 82480db1c89f2ac291e44c74274bd0b6a860a720 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:56:59 +0200 +Subject: [PATCH 06/30] block/ssh: Propagate errors to open and create methods + +Message-id: <1433764620-20506-6-git-send-email-rjones@redhat.com> +Patchwork-id: 65482 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 5/6] block/ssh: Propagate errors to open and create methods +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Markus Armbruster + +Completes the conversion to Error started in commit 015a103^..d5124c0. + +Signed-off-by: Markus Armbruster +Reviewed-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 5496fb1aebb624b379a503a8b2a156922a275fa1 +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 47 ++++++++++++++++++++++------------------------- + 1 file changed, 22 insertions(+), 25 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 07f8a2c..3b4d9e7 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -131,29 +131,34 @@ session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + g_free(msg); + } + +-/* Wrappers around error_report which make sure to dump as much +- * information from libssh2 as possible. +- */ +-static void GCC_FMT_ATTR(2, 3) +-session_error_report(BDRVSSHState *s, const char *fs, ...) ++static void GCC_FMT_ATTR(3, 4) ++sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + { + va_list args; ++ char *msg; + + va_start(args, fs); +- error_vprintf(fs, args); ++ msg = g_strdup_vprintf(fs, args); ++ va_end(args); + +- if ((s)->session) { ++ if (s->sftp) { + char *ssh_err; + int ssh_err_code; ++ unsigned long sftp_err_code; + + /* This is not an errno. See . */ + ssh_err_code = libssh2_session_last_error(s->session, + &ssh_err, NULL, 0); +- error_printf(": %s (libssh2 error code: %d)", ssh_err, ssh_err_code); +- } ++ /* See . */ ++ sftp_err_code = libssh2_sftp_last_error((s)->sftp); + +- va_end(args); +- error_printf("\n"); ++ error_setg(errp, ++ "%s: %s (libssh2 error code: %d, sftp error code: %lu)", ++ msg, ssh_err, ssh_err_code, sftp_err_code); ++ } else { ++ error_setg(errp, "%s", msg); ++ } ++ g_free(msg); + } + + static void GCC_FMT_ATTR(2, 3) +@@ -594,14 +599,14 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + path, ssh_flags, creat_mode); + s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode); + if (!s->sftp_handle) { +- session_error_report(s, "failed to open remote file '%s'", path); ++ session_error_setg(errp, s, "failed to open remote file '%s'", path); + ret = -EINVAL; + goto err; + } + + r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); + if (r < 0) { +- sftp_error_report(s, "failed to read file attributes"); ++ sftp_error_setg(errp, s, "failed to read file attributes"); + return -EINVAL; + } + +@@ -639,7 +644,6 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + Error **errp) + { +- Error *local_err = NULL; + BDRVSSHState *s = bs->opaque; + int ret; + int ssh_flags; +@@ -652,10 +656,8 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + } + + /* Start up SSH. */ +- ret = connect_to_ssh(s, options, ssh_flags, 0, &local_err); ++ ret = connect_to_ssh(s, options, ssh_flags, 0, errp); + if (ret < 0) { +- qerror_report_err(local_err); +- error_free(local_err); + goto err; + } + +@@ -686,7 +688,6 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, + Error **errp) + { + int r, ret; +- Error *local_err = NULL; + int64_t total_size = 0; + QDict *uri_options = NULL; + BDRVSSHState s; +@@ -705,10 +706,8 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, + DPRINTF("total_size=%" PRIi64, total_size); + + uri_options = qdict_new(); +- r = parse_uri(filename, uri_options, &local_err); ++ r = parse_uri(filename, uri_options, errp); + if (r < 0) { +- qerror_report_err(local_err); +- error_free(local_err); + ret = r; + goto out; + } +@@ -716,10 +715,8 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, + r = connect_to_ssh(&s, uri_options, + LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| + LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, +- 0644, &local_err); ++ 0644, errp); + if (r < 0) { +- qerror_report_err(local_err); +- error_free(local_err); + ret = r; + goto out; + } +@@ -728,7 +725,7 @@ static int ssh_create(const char *filename, QEMUOptionParameter *options, + libssh2_sftp_seek64(s.sftp_handle, total_size-1); + r2 = libssh2_sftp_write(s.sftp_handle, c, 1); + if (r2 < 0) { +- sftp_error_report(&s, "truncate failed"); ++ sftp_error_setg(errp, &s, "truncate failed"); + ret = -EINVAL; + goto out; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-update-test-070-for-vhdx.patch b/SOURCES/kvm-block-update-test-070-for-vhdx.patch new file mode 100644 index 0000000..299ed3c --- /dev/null +++ b/SOURCES/kvm-block-update-test-070-for-vhdx.patch @@ -0,0 +1,56 @@ +From 3c073988909052fb85088be3b45134fb0817286a Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Tue, 21 Jul 2015 17:30:55 +0200 +Subject: [PATCH 2/3] block: update test 070 for vhdx + +Message-id: +Patchwork-id: 67091 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] block: update test 070 for vhdx +Bugzilla: 1171576 +RH-Acked-by: Max Reitz +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +This updates test 070 for VHDX - the sample image is added, and the +expected error output is update to reflect the error message present +downstream. + +Downstream only, as this image file already exists upstream, and was +missing downstream. + +Signed-off-by: Jeff Cody +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/070 | 2 +- + tests/qemu-iotests/070.out | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/070 b/tests/qemu-iotests/070 +index 41bf100..ac23281 100755 +--- a/tests/qemu-iotests/070 ++++ b/tests/qemu-iotests/070 +@@ -56,7 +56,7 @@ _use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2 + + echo + echo "=== Verify open image read-only fails, due to dirty log ===" +-$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied" ++$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Operation not permitted" + + echo "=== Verify open image replays log ===" + $QEMU_IO -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io +diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out +index 9db8ff2..91bfb04 100644 +--- a/tests/qemu-iotests/070.out ++++ b/tests/qemu-iotests/070.out +@@ -1,7 +1,7 @@ + QA output created by 070 + + === Verify open image read-only fails, due to dirty log === +-Permission denied ++Operation not permitted + === Verify open image replays log === + read 18874368/18874368 bytes at offset 0 + 18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-vpc-prevent-overflow-if-max_table_entries-0x40.patch b/SOURCES/kvm-block-vpc-prevent-overflow-if-max_table_entries-0x40.patch new file mode 100644 index 0000000..411598a --- /dev/null +++ b/SOURCES/kvm-block-vpc-prevent-overflow-if-max_table_entries-0x40.patch @@ -0,0 +1,94 @@ +From aab4d4ef24bf36c65e4d33cf817903118061ad85 Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Wed, 29 Jul 2015 16:59:54 +0200 +Subject: [PATCH 03/13] block: vpc - prevent overflow if max_table_entries >= + 0x40000000 + +Message-id: <6ed83012cdee022f7015ed8fc7bc93abc3a8ef76.1438188988.git.jcody@redhat.com> +Patchwork-id: 67199 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/3] block: vpc - prevent overflow if max_table_entries >= 0x40000000 +Bugzilla: 1217349 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +When we allocate the pagetable based on max_table_entries, we multiply +the max table entry value by 4 to accomodate a table of 32-bit integers. +However, max_table_entries is a uint32_t, and the VPC driver accepts +ranges for that entry over 0x40000000. So during this allocation: + +s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4); + +The size arg overflows, allocating significantly less memory than +expected. + +Since qemu_try_blockalign() size argument is size_t, cast the +multiplication correctly to prevent overflow. + +The value of "max_table_entries * 4" is used elsewhere in the code as +well, so store the correct value for use in all those cases. + +We also check the Max Tables Entries value, to make sure that it is < +SIZE_MAX / 4, so we know the pagetable size will fit in size_t. + +Cc: qemu-stable@nongnu.org +Reported-by: Richard W.M. Jones +Signed-off-by: Jeff Cody +Signed-off-by: Kevin Wolf +(cherry picked from commit b15deac79530d818092cb49a8021bcce83d71b5b) +Signed-off-by: Miroslav Rezanina +--- + block/vpc.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/block/vpc.c b/block/vpc.c +index 6fdce40..1ded510 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -167,6 +167,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + uint8_t buf[HEADER_SIZE]; + uint32_t checksum; + uint64_t computed_size; ++ uint64_t pagetable_size; + int disk_type = VHD_DYNAMIC; + int ret; + +@@ -260,7 +261,17 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + goto fail; + } + +- s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4); ++ if (s->max_table_entries > SIZE_MAX / 4 || ++ s->max_table_entries > (int) INT_MAX / 4) { ++ error_setg(errp, "Max Table Entries too large (%" PRId32 ")", ++ s->max_table_entries); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ pagetable_size = (uint64_t) s->max_table_entries * 4; ++ ++ s->pagetable = qemu_try_blockalign(bs->file, pagetable_size); + if (s->pagetable == NULL) { + ret = -ENOMEM; + goto fail; +@@ -268,14 +279,13 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + + s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); + +- ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, +- s->max_table_entries * 4); ++ ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable, pagetable_size); + if (ret < 0) { + goto fail; + } + + s->free_data_block_offset = +- (s->bat_offset + (s->max_table_entries * 4) + 511) & ~511; ++ ROUND_UP(s->bat_offset + pagetable_size, 512); + + for (i = 0; i < s->max_table_entries; i++) { + be32_to_cpus(&s->pagetable[i]); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block.curl-adding-timeout-option.patch b/SOURCES/kvm-block.curl-adding-timeout-option.patch new file mode 100644 index 0000000..8a32009 --- /dev/null +++ b/SOURCES/kvm-block.curl-adding-timeout-option.patch @@ -0,0 +1,102 @@ +From 06b79081237eff3ebd8719af55265855d446f3e6 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:25 +0200 +Subject: [PATCH 25/30] block.curl: adding 'timeout' option + +Message-id: <1434022828-13037-19-git-send-email-rjones@redhat.com> +Patchwork-id: 65851 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 18/21] block.curl: adding 'timeout' option +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Daniel Henrique Barboza + +The curl hardcoded timeout (5 seconds) sometimes is not long +enough depending on the remote server configuration and network +traffic. The user should be able to set how much long he is +willing to wait for the connection. + +Adding a new option to set this timeout gives the user this +flexibility. The previous default timeout of 5 seconds will be +used if this option is not present. + +Reviewed-by: Fam Zheng +Signed-off-by: Daniel Henrique Barboza +Reviewed-by: Benoit Canet +Tested-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 212aefaa53d142baa9a22f5aadd2e72eb916c0c0 + +Note this intentionally omits the documentation changes in +'qemu-options.hx' from the upstream patch. + +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index 2486449..1f1df4f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -63,6 +63,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_NUM_ACB 8 + #define SECTOR_SIZE 512 + #define READ_AHEAD_DEFAULT (256 * 1024) ++#define CURL_TIMEOUT_DEFAULT 5 + + #define FIND_RET_NONE 0 + #define FIND_RET_OK 1 +@@ -71,6 +72,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_BLOCK_OPT_URL "url" + #define CURL_BLOCK_OPT_READAHEAD "readahead" + #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" ++#define CURL_BLOCK_OPT_TIMEOUT "timeout" + + struct BDRVCURLState; + +@@ -109,6 +111,7 @@ typedef struct BDRVCURLState { + char *url; + size_t readahead_size; + bool sslverify; ++ int timeout; + bool accept_range; + } BDRVCURLState; + +@@ -379,7 +382,7 @@ static CURLState *curl_init_state(BDRVCURLState *s) + curl_easy_setopt(state->curl, CURLOPT_URL, s->url); + curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, + (long) s->sslverify); +- curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); ++ curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, s->timeout); + curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, + (void *)curl_read_cb); + curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); +@@ -443,6 +446,11 @@ static QemuOptsList runtime_opts = { + .type = QEMU_OPT_BOOL, + .help = "Verify SSL certificate" + }, ++ { ++ .name = CURL_BLOCK_OPT_TIMEOUT, ++ .type = QEMU_OPT_NUMBER, ++ .help = "Curl timeout" ++ }, + { /* end of list */ } + }, + }; +@@ -475,6 +483,9 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + goto out_noclean; + } + ++ s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, ++ CURL_TIMEOUT_DEFAULT); ++ + s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); + + file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-build-reenable-local-builds-to-pass-enable-debug-RHE.patch b/SOURCES/kvm-build-reenable-local-builds-to-pass-enable-debug-RHE.patch new file mode 100644 index 0000000..4de900b --- /dev/null +++ b/SOURCES/kvm-build-reenable-local-builds-to-pass-enable-debug-RHE.patch @@ -0,0 +1,80 @@ +From 984faac66812652082fc9aa46eceb21669c1131b Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 10 Feb 2015 19:41:34 +0100 +Subject: [PATCH 11/16] build: reenable local builds to pass --enable-debug + (RHEL only) + +Message-id: <1423597294-16022-2-git-send-email-lersek@redhat.com> +Patchwork-id: 63788 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/1] build: reenable local builds to pass --enable-debug (RHEL only) +Bugzilla: +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Max Reitz + +RHEL-7 commit f6852e27 dropped the "isa-ide" device, and observed: + + Unresolved extern symbols pose no real danger, because they fail safely + at link time. Note for the curious: the optimizer gets rid of the + reference to isa_ide_init() in hw/i386/pc_piix.c. + +For local builds it is sometimes useful to pass --enable-debug to the +configure script. However that flag disables the optimizer, and the +isa_ide_init() call is not eliminated during compilation; it reaches the +linker. The linker then barfs + + LINK x86_64-softmmu/qemu-system-x86_64 + hw/i386/pc_piix.o: In function `pc_init1': + .../hw/i386/pc_piix.c:221: undefined reference to `isa_ide_init' + collect2: error: ld returned 1 exit status + +Provide a stub implementation for isa_ide_init(), reenabling local debug +builds. + +No copyright notice is added to the top of the new file, following the +pattern set by other stub files. + +Signed-off-by: Laszlo Ersek +--- + stubs/Makefile.objs | 1 + + stubs/ide-isa.c | 12 ++++++++++++ + 2 files changed, 13 insertions(+) + create mode 100644 stubs/ide-isa.c + +Signed-off-by: Miroslav Rezanina +--- + stubs/Makefile.objs | 1 + + stubs/ide-isa.c | 12 ++++++++++++ + 2 files changed, 13 insertions(+) + create mode 100644 stubs/ide-isa.c + +diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs +index 4b2cb7d..590008e 100644 +--- a/stubs/Makefile.objs ++++ b/stubs/Makefile.objs +@@ -26,3 +26,4 @@ stub-obj-y += vm-stop.o + stub-obj-y += vmstate.o + stub-obj-$(CONFIG_WIN32) += fd-register.o + stub-obj-y += cpus.o ++stub-obj-y += ide-isa.o +diff --git a/stubs/ide-isa.c b/stubs/ide-isa.c +new file mode 100644 +index 0000000..4074aff +--- /dev/null ++++ b/stubs/ide-isa.c +@@ -0,0 +1,12 @@ ++#include ++#include ++ ++ISADevice *isa_ide_init(ISABus *bus, int iobase, int iobase2, int isairq, ++ DriveInfo *hd0, DriveInfo *hd1) ++{ ++ /* ++ * In theory the real isa_ide_init() function can return NULL, but no ++ * caller actually checks for that. Make sure we go out with a clear bang. ++ */ ++ abort(); ++} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-configure-Add-handling-code-for-AArch64-targets.patch b/SOURCES/kvm-configure-Add-handling-code-for-AArch64-targets.patch new file mode 100644 index 0000000..e88585a --- /dev/null +++ b/SOURCES/kvm-configure-Add-handling-code-for-AArch64-targets.patch @@ -0,0 +1,68 @@ +From de5ec0b147e227e4429033070e432f7b5b6b749f Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Tue, 2 Jun 2015 13:21:51 +0200 +Subject: [PATCH 4/8] configure: Add handling code for AArch64 targets + +Message-id: <33907397e8692eaafe8700f27021516eab227257.1433250807.git.mrezanin@redhat.com> +Patchwork-id: 65306 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/4] configure: Add handling code for AArch64 targets +Bugzilla: 1217850 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Wei Huang +RH-Acked-by: Jeff Nelson + +From: Alexander Graf + +Add the necessary code to configure to handle AArch64 as a target +CPU (we already have some code for supporting it as host). Note +that this doesn't enable the AArch64 targets yet. + +Signed-off-by: Alexander Graf +Signed-off-by: John Rigby +Signed-off-by: Peter Maydell +Message-id: 1378235544-22290-23-git-send-email-peter.maydell@linaro.org +Message-id: 1368505980-17151-12-git-send-email-john.rigby@linaro.org +[PMM: + * don't need to set TARGET_ABI_DIR to aarch64 as that is the default + * don't build nwfpe -- this is 32 bit legacy only + * rewrite commit message + * add aarch64 to the list of "fdt required" targets +] +Signed-off-by: Peter Maydell +(cherry-picked from 6a49fa95c98cd155f7aaf48e5c6fa6bb6adea862) +Signed-off-by: Miroslav Rezanina + +Signed-off-by: Miroslav Rezanina +--- + configure | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index 4f63345..7cc7725 100755 +--- a/configure ++++ b/configure +@@ -2650,7 +2650,7 @@ fi + fdt_required=no + for target in $target_list; do + case $target in +- arm*-softmmu|ppc*-softmmu|microblaze*-softmmu) ++ aarch64*-softmmu|arm*-softmmu|ppc*-softmmu|microblaze*-softmmu) + fdt_required=yes + ;; + esac +@@ -4383,6 +4383,11 @@ case "$target_arch2" in + target_nptl="yes" + gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" + ;; ++ aarch64) ++ TARGET_BASE_ARCH=arm ++ bflt="yes" ++ gdb_xml_files="aarch64-core.xml" ++ ;; + cris) + target_nptl="yes" + ;; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-configure-Add-support-for-tcmalloc.patch b/SOURCES/kvm-configure-Add-support-for-tcmalloc.patch new file mode 100644 index 0000000..73fbf0c --- /dev/null +++ b/SOURCES/kvm-configure-Add-support-for-tcmalloc.patch @@ -0,0 +1,129 @@ +From 7016ef484a8150337f22f45f694c0901c5ae0a26 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 26 Jun 2015 11:23:50 +0200 +Subject: [PATCH 10/10] configure: Add support for tcmalloc + +Message-id: <1435317831-6743-1-git-send-email-pbonzini@redhat.com> +Patchwork-id: 66518 +O-Subject: [RHEL7.2 qemu-kvm PATCH] configure: Add support for tcmalloc +Bugzilla: 1213881 +RH-Acked-by: Jeff Nelson +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +This adds "--enable-tcmalloc" and "--disable-tcmalloc" to allow linking +to libtcmalloc from gperftools. + +tcmalloc is a malloc implementation that works well with threads and is +fast, so it is good for performance. + +It is disabled by default, because the MALLOC_PERTURB_ flag we use in +tests doesn't work with tcmalloc. However we can enable tcmalloc +specific heap checker and profilers later. + +An IOPS gain can be observed with virtio-blk-dataplane, other parts of +QEMU will directly benefit from it as well: + +========================================================== + glibc malloc +---------------------------------------------------------- +rw bs iodepth bw iops latency +read 4k 1 150 38511 24 +---------------------------------------------------------- + +========================================================== + tcmalloc +---------------------------------------------------------- +rw bs iodepth bw iops latency +read 4k 1 156 39969 23 +---------------------------------------------------------- + +Signed-off-by: Fam Zheng +Message-Id: <1427338992-27057-1-git-send-email-famz@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2847b46958ab0bd604e1b3fcafba0f5ba4375833) +Signed-off-by: Miroslav Rezanina + +Conflicts: + configure + +Note on the RHEL7 part: + malloc(1) would fail to compile due to -D_FORTIFY_SOURCE=2 that + configure passes in --extra-cflags. The flag enables warnings + for unused result of malloc. However, QEMU already knows about + -D_FORTIFY_SOURCE and enables it after configure tests are run. + So, remove it from --extra-cflags and trust configure to do the + right thing. +--- + configure | 24 ++++++++++++++++++++++++ + redhat/qemu-kvm.spec.template | 10 ++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/configure b/configure +index 85dbfb0..5877e82 100755 +--- a/configure ++++ b/configure +@@ -250,6 +250,7 @@ libssh2="" + live_block_ops="yes" + live_block_migration="no" + vhdx="" ++tcmalloc="no" + + # parse CC options first + for opt do +@@ -972,6 +973,10 @@ for opt do + ;; + --disable-vhdx) vhdx="no" + ;; ++ --disable-tcmalloc) tcmalloc="no" ++ ;; ++ --enable-tcmalloc) tcmalloc="yes" ++ ;; + *) echo "ERROR: unknown option $opt"; show_help="yes" + ;; + esac +@@ -1253,6 +1258,8 @@ echo " --disable-live-block-migration disable live block migration" + echo " --enable-live-block-migration enable live block migration" + echo " --disable-vhdx disables support for the Microsoft VHDX image format" + echo " --enable-vhdx enable support for the Microsoft VHDX image format" ++echo " --disable-tcmalloc disable tcmalloc support" ++echo " --enable-tcmalloc enable tcmalloc support" + echo "" + echo "NOTE: The object files are built at the place where configure is launched" + exit 1 +@@ -2878,6 +2885,22 @@ if compile_prog "" "" ; then + fi + + ########################################## ++# tcmalloc probe ++ ++if test "$tcmalloc" = "yes" ; then ++ cat > $TMPC << EOF ++#include ++int main(void) { malloc(1); return 0; } ++EOF ++ ++ if compile_prog "" "-ltcmalloc" ; then ++ LIBS="-ltcmalloc $LIBS" ++ else ++ feature_not_found "tcmalloc" "install gperftools devel" ++ fi ++fi ++ ++########################################## + # signalfd probe + signalfd="no" + cat > $TMPC << EOF +@@ -3744,6 +3767,7 @@ echo "Live block migration $live_block_migration" + echo "vhdx $vhdx" + echo "lzo support $lzo" + echo "snappy support $snappy" ++echo "tcmalloc support $tcmalloc" + + if test "$sdl_too_old" = "yes"; then + echo "-> Your SDL version is too old - please upgrade to have SDL support" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-configure-Require-libfdt-for-arm-ppc-microblaze-soft.patch b/SOURCES/kvm-configure-Require-libfdt-for-arm-ppc-microblaze-soft.patch new file mode 100644 index 0000000..2993e1b --- /dev/null +++ b/SOURCES/kvm-configure-Require-libfdt-for-arm-ppc-microblaze-soft.patch @@ -0,0 +1,69 @@ +From 72b1305cb8cbcd0847a435326c7fa90273ac9c56 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Tue, 2 Jun 2015 13:21:50 +0200 +Subject: [PATCH 3/8] configure: Require libfdt for arm, ppc, microblaze + softmmu targets + +Message-id: +Patchwork-id: 65305 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/4] configure: Require libfdt for arm, ppc, microblaze softmmu targets +Bugzilla: 1217850 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Wei Huang +RH-Acked-by: Jeff Nelson + +From: Peter Maydell + +A number of our softmmu targets (PPC, ARM, Microblaze) now more or +less require flattened device tree support for various board models +to work correctly. Make libfdt mandatory if the target list includes +these, rather than building unhelpful half-functional binaries. + +Signed-off-by: Peter Maydell +Reviewed-by: Edgar E. Iglesias +Reviewed-by: Peter Crosthwaite +Tested-by: Edgar E. Iglesias +Message-id: 1369409217-7553-2-git-send-email-peter.maydell@linaro.org +(cherry-picked from e169e1e1ae1e75c522f932554890fb0f2f3e9999) +Signed-off-by: Miroslav Rezanina + +Signed-off-by: Miroslav Rezanina +--- + configure | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/configure b/configure +index 1583359..4f63345 100755 +--- a/configure ++++ b/configure +@@ -2645,6 +2645,26 @@ fi + + ########################################## + # fdt probe ++# fdt support is mandatory for at least some target architectures, ++# so insist on it if we're building those system emulators. ++fdt_required=no ++for target in $target_list; do ++ case $target in ++ arm*-softmmu|ppc*-softmmu|microblaze*-softmmu) ++ fdt_required=yes ++ ;; ++ esac ++done ++ ++if test "$fdt_required" = "yes"; then ++ if test "$fdt" = "no"; then ++ error_exit "fdt disabled but some requested targets require it." \ ++ "You can turn off fdt only if you also disable all the system emulation" \ ++ "targets which need it (by specifying a cut down --target-list)." ++ fi ++ fdt=yes ++fi ++ + if test "$fdt" != "no" ; then + fdt_libs="-lfdt" + cat > $TMPC << EOF +-- +1.8.3.1 + diff --git a/SOURCES/kvm-configure-permit-compilation-on-arm-aarch64.patch b/SOURCES/kvm-configure-permit-compilation-on-arm-aarch64.patch new file mode 100644 index 0000000..73bf945 --- /dev/null +++ b/SOURCES/kvm-configure-permit-compilation-on-arm-aarch64.patch @@ -0,0 +1,67 @@ +From f4e64f793b273e319587b9052c9f8cde77b6db52 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Tue, 2 Jun 2015 13:21:52 +0200 +Subject: [PATCH 5/8] configure: permit compilation on arm aarch64 + +Message-id: <40b5931574ca633cff2c4a27507680b321009906.1433250807.git.mrezanin@redhat.com> +Patchwork-id: 65307 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/4] configure: permit compilation on arm aarch64 +Bugzilla: 1217850 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Wei Huang +RH-Acked-by: Jeff Nelson + +From: Claudio Fontana + +support compiling on aarch64. + +Reviewed-by: Peter Maydell +Signed-off-by: Claudio Fontana +Reviewed-by: Richard Henderson +Message-id: 51A5C5ED.90103@huawei.com +Signed-off-by: Peter Maydell +(cherry-picked from 1f0803137df68c1fc02ebd0c5ec2e7aad54bbf3b) +Signed-off-by: Miroslav Rezanina + +Signed-off-by: Miroslav Rezanina +--- + configure | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/configure b/configure +index 7cc7725..85dbfb0 100755 +--- a/configure ++++ b/configure +@@ -394,6 +394,8 @@ elif check_define __s390__ ; then + fi + elif check_define __arm__ ; then + cpu="arm" ++elif check_define __aarch64__ ; then ++ cpu="aarch64" + elif check_define __hppa__ ; then + cpu="hppa" + else +@@ -416,6 +418,9 @@ case "$cpu" in + armv*b|armv*l|arm) + cpu="arm" + ;; ++ aarch64) ++ cpu="aarch64" ++ ;; + hppa|parisc|parisc64) + cpu="hppa" + ;; +@@ -4306,6 +4311,9 @@ if test "$linux" = "yes" ; then + s390x) + linux_arch=s390 + ;; ++ aarch64) ++ linux_arch=arm64 ++ ;; + *) + # For most CPUs the kernel architecture name and QEMU CPU name match. + linux_arch="$cpu" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Add-sslverify-option.patch b/SOURCES/kvm-curl-Add-sslverify-option.patch new file mode 100644 index 0000000..39c9304 --- /dev/null +++ b/SOURCES/kvm-curl-Add-sslverify-option.patch @@ -0,0 +1,88 @@ +From 00346b0ddbb4cffa91b69421353ab20f8be17f9e Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:22 +0200 +Subject: [PATCH 22/30] curl: Add sslverify option + +Message-id: <1434022828-13037-16-git-send-email-rjones@redhat.com> +Patchwork-id: 65850 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 15/21] curl: Add sslverify option +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +This allows qemu to use images over https with a self-signed certificate. It +defaults to verifying the certificate. + +Signed-off-by: Matthew Booth +Signed-off-by: Kevin Wolf + +Upstream-status: 97a3ea57198b39b8366cd2a7514707abdcd0a7bc +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/block/curl.c b/block/curl.c +index e97682f..e48cc87 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -23,6 +23,7 @@ + */ + #include "qemu-common.h" + #include "block/block_int.h" ++#include "qapi/qmp/qbool.h" + #include + + // #define DEBUG +@@ -69,6 +70,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + + #define CURL_BLOCK_OPT_URL "url" + #define CURL_BLOCK_OPT_READAHEAD "readahead" ++#define CURL_BLOCK_OPT_SSLVERIFY "sslverify" + + struct BDRVCURLState; + +@@ -106,6 +108,7 @@ typedef struct BDRVCURLState { + CURLState states[CURL_NUM_STATES]; + char *url; + size_t readahead_size; ++ bool sslverify; + bool accept_range; + } BDRVCURLState; + +@@ -374,6 +377,8 @@ static CURLState *curl_init_state(BDRVCURLState *s) + return NULL; + } + curl_easy_setopt(state->curl, CURLOPT_URL, s->url); ++ curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, ++ (long) s->sslverify); + curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); + curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, + (void *)curl_read_cb); +@@ -433,6 +438,11 @@ static QemuOptsList runtime_opts = { + .type = QEMU_OPT_SIZE, + .help = "Readahead size", + }, ++ { ++ .name = CURL_BLOCK_OPT_SSLVERIFY, ++ .type = QEMU_OPT_BOOL, ++ .help = "Verify SSL certificate" ++ }, + { /* end of list */ } + }, + }; +@@ -465,6 +475,8 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + goto out_noclean; + } + ++ s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); ++ + file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); + if (file == NULL) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "curl block driver requires " +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch b/SOURCES/kvm-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch new file mode 100644 index 0000000..42f12f8 --- /dev/null +++ b/SOURCES/kvm-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch @@ -0,0 +1,126 @@ +From 1eeb050a2cc6c582c390614080fbeaea019b2dac Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:26 +0200 +Subject: [PATCH 26/30] curl: Allow a cookie or cookies to be sent with + http/https requests. + +Message-id: <1434022828-13037-20-git-send-email-rjones@redhat.com> +Patchwork-id: 65854 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 19/21] curl: Allow a cookie or cookies to be sent with http/https requests. +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: "Richard W.M. Jones" + +In order to access VMware ESX efficiently, we need to send a session +cookie. This patch is very simple and just allows you to send that +session cookie. It punts on the question of how you get the session +cookie in the first place, but in practice you can just run a `curl' +command against the server and extract the cookie that way. + +To use it, add file.cookie to the curl URL. For example: + +$ qemu-img info 'json: { + "file.driver":"https", + "file.url":"https://vcenter/folder/Windows%202003/Windows%202003-flat.vmdk?dcPath=Datacenter&dsName=datastore1", + "file.sslverify":"off", + "file.cookie":"vmware_soap_session=\"52a01262-bf93-ccce-d379-8dabb3e55560\""}' +image: [...] +file format: raw +virtual size: 8.0G (8589934592 bytes) +disk size: unavailable + +Signed-off-by: Richard W.M. Jones +Signed-off-by: Stefan Hajnoczi + +Upstream-status: a94f83d94fdf907680f068f1be7ad13d1f697067 + +Note this intentionally omits the documentation changes in +'qemu-options.hx' from the upstream patch. + +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block/curl.c b/block/curl.c +index 1f1df4f..ca881ee 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -73,6 +73,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_BLOCK_OPT_READAHEAD "readahead" + #define CURL_BLOCK_OPT_SSLVERIFY "sslverify" + #define CURL_BLOCK_OPT_TIMEOUT "timeout" ++#define CURL_BLOCK_OPT_COOKIE "cookie" + + struct BDRVCURLState; + +@@ -112,6 +113,7 @@ typedef struct BDRVCURLState { + size_t readahead_size; + bool sslverify; + int timeout; ++ char *cookie; + bool accept_range; + } BDRVCURLState; + +@@ -382,6 +384,9 @@ static CURLState *curl_init_state(BDRVCURLState *s) + curl_easy_setopt(state->curl, CURLOPT_URL, s->url); + curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER, + (long) s->sslverify); ++ if (s->cookie) { ++ curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie); ++ } + curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, s->timeout); + curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, + (void *)curl_read_cb); +@@ -451,6 +456,11 @@ static QemuOptsList runtime_opts = { + .type = QEMU_OPT_NUMBER, + .help = "Curl timeout" + }, ++ { ++ .name = CURL_BLOCK_OPT_COOKIE, ++ .type = QEMU_OPT_STRING, ++ .help = "Pass the cookie or list of cookies with each request" ++ }, + { /* end of list */ } + }, + }; +@@ -463,6 +473,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + QemuOpts *opts; + Error *local_err = NULL; + const char *file; ++ const char *cookie; + double d; + + static int inited = 0; +@@ -488,6 +499,9 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + + s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); + ++ cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); ++ s->cookie = g_strdup(cookie); ++ + file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); + if (file == NULL) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "curl block driver requires " +@@ -556,6 +570,7 @@ out: + curl_easy_cleanup(state->curl); + state->curl = NULL; + out_noclean: ++ g_free(s->cookie); + g_free(s->url); + qemu_opts_del(opts); + return -EINVAL; +@@ -696,6 +711,7 @@ static void curl_close(BlockDriverState *bs) + qemu_del_timer(s->timer); + qemu_free_timer(s->timer); + ++ g_free(s->cookie); + g_free(s->url); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Eliminate-unnecessary-use-of-curl_multi_socket_.patch b/SOURCES/kvm-curl-Eliminate-unnecessary-use-of-curl_multi_socket_.patch new file mode 100644 index 0000000..a1c36b2 --- /dev/null +++ b/SOURCES/kvm-curl-Eliminate-unnecessary-use-of-curl_multi_socket_.patch @@ -0,0 +1,142 @@ +From 2b07b0558685c234fd93214be705a4feb058e27b Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:16 +0200 +Subject: [PATCH 16/30] curl: Eliminate unnecessary use of + curl_multi_socket_all + +Message-id: <1434022828-13037-10-git-send-email-rjones@redhat.com> +Patchwork-id: 65844 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 09/21] curl: Eliminate unnecessary use of curl_multi_socket_all +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +curl_multi_socket_all is a deprecated catch-all which checks for +activities on all open curl sockets. We have enough information from +the event loop to check only the sockets with activity. This change +removes use of curl_multi_socket_all in favour of +curl_multi_socket_action called with the relevant handle. + +At the same time, it also ensures that the driver only checks for +completion of read operations after reading from a socket, rather than +both reading and writing. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: 838ef602498b8d1985a231a06f5e328e2946a81d +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index e4332c5..b19e632 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -71,6 +71,7 @@ typedef struct CURLState + struct BDRVCURLState *s; + CURLAIOCB *acb[CURL_NUM_ACB]; + CURL *curl; ++ curl_socket_t sock_fd; + char *orig_buf; + size_t buf_start; + size_t buf_off; +@@ -92,6 +93,7 @@ typedef struct BDRVCURLState { + static void curl_clean_state(CURLState *s); + static void curl_multi_do(void *arg); + static int curl_aio_flush(void *opaque); ++static void curl_multi_read(void *arg); + + #ifdef NEED_CURL_TIMER_CALLBACK + static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) +@@ -113,17 +115,21 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque) + static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + void *s, void *sp) + { ++ CURLState *state = NULL; ++ curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state); ++ state->sock_fd = fd; ++ + DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd); + switch (action) { + case CURL_POLL_IN: +- qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, curl_aio_flush, s); ++ qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, curl_aio_flush, state); + break; + case CURL_POLL_OUT: +- qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, curl_aio_flush, s); ++ qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, curl_aio_flush, state); + break; + case CURL_POLL_INOUT: +- qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, +- curl_aio_flush, s); ++ qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, ++ curl_aio_flush, state); + break; + case CURL_POLL_REMOVE: + qemu_aio_set_fd_handler(fd, NULL, NULL, NULL, NULL); +@@ -236,7 +242,7 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, + return FIND_RET_NONE; + } + +-static void curl_multi_read(BDRVCURLState *s) ++static void curl_multi_check_completion(BDRVCURLState *s) + { + int msgs_in_queue; + +@@ -286,19 +292,26 @@ static void curl_multi_read(BDRVCURLState *s) + + static void curl_multi_do(void *arg) + { +- BDRVCURLState *s = (BDRVCURLState *)arg; ++ CURLState *s = (CURLState *)arg; + int running; + int r; + +- if (!s->multi) { ++ if (!s->s->multi) { + return; + } + + do { +- r = curl_multi_socket_all(s->multi, &running); ++ r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running); + } while(r == CURLM_CALL_MULTI_PERFORM); + +- curl_multi_read(s); ++} ++ ++static void curl_multi_read(void *arg) ++{ ++ CURLState *s = (CURLState *)arg; ++ ++ curl_multi_do(arg); ++ curl_multi_check_completion(s->s); + } + + static void curl_multi_timeout_do(void *arg) +@@ -313,7 +326,7 @@ static void curl_multi_timeout_do(void *arg) + + curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); + +- curl_multi_read(s); ++ curl_multi_check_completion(s); + #else + abort(); + #endif +@@ -517,7 +530,6 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + // initialize the multi interface! + + s->multi = curl_multi_init(); +- curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); + curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); + #ifdef NEED_CURL_TIMER_CALLBACK + curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Ensure-all-informationals-are-checked-for-compl.patch b/SOURCES/kvm-curl-Ensure-all-informationals-are-checked-for-compl.patch new file mode 100644 index 0000000..8d37630 --- /dev/null +++ b/SOURCES/kvm-curl-Ensure-all-informationals-are-checked-for-compl.patch @@ -0,0 +1,107 @@ +From 92a8426bb06ecb65af6fc6953e11870872bf52d1 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:17 +0200 +Subject: [PATCH 17/30] curl: Ensure all informationals are checked for + completion + +Message-id: <1434022828-13037-11-git-send-email-rjones@redhat.com> +Patchwork-id: 65845 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 10/21] curl: Ensure all informationals are checked for completion +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +According to the documentation, the correct way to ensure all +informationals have been returned by curl_multi_info_read is to loop +until it returns NULL. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: 1f2cead324436da25c3607f4b957f0198a01fc01 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 53 +++++++++++++++++++++++------------------------------ + 1 file changed, 23 insertions(+), 30 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index b19e632..41cf015 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -248,46 +248,39 @@ static void curl_multi_check_completion(BDRVCURLState *s) + + /* Try to find done transfers, so we can free the easy + * handle again. */ +- do { ++ for (;;) { + CURLMsg *msg; + msg = curl_multi_info_read(s->multi, &msgs_in_queue); + ++ /* Quit when there are no more completions */ + if (!msg) + break; +- if (msg->msg == CURLMSG_NONE) +- break; + +- switch (msg->msg) { +- case CURLMSG_DONE: +- { +- CURLState *state = NULL; +- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, +- (char **)&state); +- +- /* ACBs for successful messages get completed in curl_read_cb */ +- if (msg->data.result != CURLE_OK) { +- int i; +- for (i = 0; i < CURL_NUM_ACB; i++) { +- CURLAIOCB *acb = state->acb[i]; +- +- if (acb == NULL) { +- continue; +- } +- +- acb->common.cb(acb->common.opaque, -EIO); +- qemu_aio_release(acb); +- state->acb[i] = NULL; ++ if (msg->msg == CURLMSG_DONE) { ++ CURLState *state = NULL; ++ curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, ++ (char **)&state); ++ ++ /* ACBs for successful messages get completed in curl_read_cb */ ++ if (msg->data.result != CURLE_OK) { ++ int i; ++ for (i = 0; i < CURL_NUM_ACB; i++) { ++ CURLAIOCB *acb = state->acb[i]; ++ ++ if (acb == NULL) { ++ continue; + } +- } + +- curl_clean_state(state); +- break; ++ acb->common.cb(acb->common.opaque, -EIO); ++ qemu_aio_release(acb); ++ state->acb[i] = NULL; ++ } + } +- default: +- msgs_in_queue = 0; +- break; ++ ++ curl_clean_state(state); ++ break; + } +- } while(msgs_in_queue); ++ } + } + + static void curl_multi_do(void *arg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Fix-build-when-curl_multi_socket_action-isn-t-a.patch b/SOURCES/kvm-curl-Fix-build-when-curl_multi_socket_action-isn-t-a.patch new file mode 100644 index 0000000..76b8e3e --- /dev/null +++ b/SOURCES/kvm-curl-Fix-build-when-curl_multi_socket_action-isn-t-a.patch @@ -0,0 +1,54 @@ +From e1ae27052f1c226e2cabe2199ab98d7e243c8cd2 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:19 +0200 +Subject: [PATCH 19/30] curl: Fix build when curl_multi_socket_action isn't + available + +Message-id: <1434022828-13037-13-git-send-email-rjones@redhat.com> +Patchwork-id: 65846 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 12/21] curl: Fix build when curl_multi_socket_action isn't available +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +Signed-off-by: Matthew Booth +Signed-off-by: Kevin Wolf + +Upstream-status: 9aedd5a5d607216e41bfa6a2c1f7f5d2b17041c3 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/block/curl.c b/block/curl.c +index 1bff71a..be2d3f4 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -37,6 +37,21 @@ + #if LIBCURL_VERSION_NUM >= 0x071000 + /* The multi interface timer callback was introduced in 7.16.0 */ + #define NEED_CURL_TIMER_CALLBACK ++#define HAVE_SOCKET_ACTION ++#endif ++ ++#ifndef HAVE_SOCKET_ACTION ++/* If curl_multi_socket_action isn't available, define it statically here in ++ * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is ++ * less efficient but still safe. */ ++static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, ++ curl_socket_t sockfd, ++ int ev_bitmask, ++ int *running_handles) ++{ ++ return curl_multi_socket(multi_handle, sockfd, running_handles); ++} ++#define curl_multi_socket_action __curl_multi_socket_action + #endif + + #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Fix-hang-reading-from-slow-connections.patch b/SOURCES/kvm-curl-Fix-hang-reading-from-slow-connections.patch new file mode 100644 index 0000000..48f901b --- /dev/null +++ b/SOURCES/kvm-curl-Fix-hang-reading-from-slow-connections.patch @@ -0,0 +1,49 @@ +From 188c4737c54787bbd734c628121f7f0e4f833cd1 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:18 +0200 +Subject: [PATCH 18/30] curl: Fix hang reading from slow connections + +Message-id: <1434022828-13037-12-git-send-email-rjones@redhat.com> +Patchwork-id: 65847 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 11/21] curl: Fix hang reading from slow connections +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +When receiving a new aio read request, we first look for an existing +transaction whose range will cover the read request by the time it +completes. However, we weren't checking that the existing transaction +was still active. If it had timed out, we were adding the request to a +transaction which would never complete and had already been cancelled, +resulting in a hang. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: b7079df4100069959f4e9d90d5cb5ba7d4ebbf1a +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index 41cf015..1bff71a 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -220,7 +220,8 @@ static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len, + } + + // Wait for unfinished chunks +- if ((start >= state->buf_start) && ++ if (state->in_use && ++ (start >= state->buf_start) && + (start <= buf_fend) && + (end >= state->buf_start) && + (end <= buf_fend)) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Fix-long-line.patch b/SOURCES/kvm-curl-Fix-long-line.patch new file mode 100644 index 0000000..0475741 --- /dev/null +++ b/SOURCES/kvm-curl-Fix-long-line.patch @@ -0,0 +1,42 @@ +From 4df5e14e48bd02ea2b6414d1e8ea105ab510dccd Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:09 +0200 +Subject: [PATCH 09/30] curl: Fix long line + +Message-id: <1434022828-13037-3-git-send-email-rjones@redhat.com> +Patchwork-id: 65837 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 02/21] curl: Fix long line +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: f6246509be602369cfa1250965e1e62a0c62c99f +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index a877dea..f69e337 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -243,7 +243,8 @@ static void curl_multi_do(void *arg) + case CURLMSG_DONE: + { + CURLState *state = NULL; +- curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char**)&state); ++ curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, ++ (char **)&state); + + /* ACBs for successful messages get completed in curl_read_cb */ + if (msg->data.result != CURLE_OK) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Fix-return-from-curl_read_cb-with-invalid-state.patch b/SOURCES/kvm-curl-Fix-return-from-curl_read_cb-with-invalid-state.patch new file mode 100644 index 0000000..5431dcb --- /dev/null +++ b/SOURCES/kvm-curl-Fix-return-from-curl_read_cb-with-invalid-state.patch @@ -0,0 +1,53 @@ +From 331b54ab7f261fd24844f7345aaaad03ef474e7e Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:11 +0200 +Subject: [PATCH 11/30] curl: Fix return from curl_read_cb with invalid state + +Message-id: <1434022828-13037-5-git-send-email-rjones@redhat.com> +Patchwork-id: 65839 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 04/21] curl: Fix return from curl_read_cb with invalid state +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +A curl write callback is supposed to return the number of bytes it +handled. curl_read_cb would have erroneously reported it had handled +all bytes in the event that the internal curl state was invalid. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: 38bbc0a580f9f10570b1d1b5d3e92f0e6feb2970 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index d399e3a..8c707e1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -132,7 +132,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + DPRINTF("CURL: Just reading %zd bytes\n", realsize); + + if (!s || !s->orig_buf) +- goto read_end; ++ return 0; + + if (s->buf_off >= s->buf_len) { + /* buffer full, read nothing */ +@@ -157,7 +157,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + } + } + +-read_end: + return realsize; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Handle-failure-for-potentially-large-allocation.patch b/SOURCES/kvm-curl-Handle-failure-for-potentially-large-allocation.patch new file mode 100644 index 0000000..c0e6daf --- /dev/null +++ b/SOURCES/kvm-curl-Handle-failure-for-potentially-large-allocation.patch @@ -0,0 +1,53 @@ +From e7ec271f6886eb7c37e200309d677a0f4dc32efe Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:24 +0200 +Subject: [PATCH 24/30] curl: Handle failure for potentially large allocations + +Message-id: <1434022828-13037-18-git-send-email-rjones@redhat.com> +Patchwork-id: 65852 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 17/21] curl: Handle failure for potentially large allocations +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Kevin Wolf + +Some code in the block layer makes potentially huge allocations. Failure +is not completely unexpected there, so avoid aborting qemu and handle +out-of-memory situations gracefully. + +This patch addresses the allocations in the curl block driver. + +Signed-off-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Benoit Canet + +Upstream-status: 8dc7a7725bd6db2aa7e3c09b49bc21a1a25f40cb +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index d95789a..2486449 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -618,7 +618,13 @@ static void curl_readv_bh_cb(void *p) + state->buf_start = start; + state->buf_len = acb->end + s->readahead_size; + end = MIN(start + state->buf_len, s->len) - 1; +- state->orig_buf = g_malloc(state->buf_len); ++ state->orig_buf = g_try_malloc(state->buf_len); ++ if (state->buf_len && state->orig_buf == NULL) { ++ curl_clean_state(state); ++ acb->common.cb(acb->common.opaque, -ENOMEM); ++ qemu_aio_release(acb); ++ return; ++ } + state->acb[0] = acb; + + snprintf(state->range, 127, "%zd-%zd", start, end); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Remove-broken-parsing-of-options-from-url.patch b/SOURCES/kvm-curl-Remove-broken-parsing-of-options-from-url.patch new file mode 100644 index 0000000..9ff8e88 --- /dev/null +++ b/SOURCES/kvm-curl-Remove-broken-parsing-of-options-from-url.patch @@ -0,0 +1,129 @@ +From d935f2a3eafd649a2b40c27c8b6f8536a2e486e5 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:20 +0200 +Subject: [PATCH 20/30] curl: Remove broken parsing of options from url + +Message-id: <1434022828-13037-14-git-send-email-rjones@redhat.com> +Patchwork-id: 65848 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 13/21] curl: Remove broken parsing of options from url +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +The block layer now supports a generic json syntax for passing option parameters +explicitly, making parsing of options from the url redundant. + +Signed-off-by: Matthew Booth +Signed-off-by: Kevin Wolf + +Upstream-status: e3542c67af4cb4fd90e3be912630be9acd97b9c0 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 52 ++++++++++------------------------------------------ + 1 file changed, 10 insertions(+), 42 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index be2d3f4..67ea05f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -61,12 +61,15 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_NUM_STATES 8 + #define CURL_NUM_ACB 8 + #define SECTOR_SIZE 512 +-#define READ_AHEAD_SIZE (256 * 1024) ++#define READ_AHEAD_DEFAULT (256 * 1024) + + #define FIND_RET_NONE 0 + #define FIND_RET_OK 1 + #define FIND_RET_WAIT 2 + ++#define CURL_BLOCK_OPT_URL "url" ++#define CURL_BLOCK_OPT_READAHEAD "readahead" ++ + struct BDRVCURLState; + + typedef struct CURLAIOCB { +@@ -411,43 +414,7 @@ static void curl_clean_state(CURLState *s) + static void curl_parse_filename(const char *filename, QDict *options, + Error **errp) + { +- +- #define RA_OPTSTR ":readahead=" +- char *file; +- char *ra; +- const char *ra_val; +- int parse_state = 0; +- +- file = g_strdup(filename); +- +- /* Parse a trailing ":readahead=#:" param, if present. */ +- ra = file + strlen(file) - 1; +- while (ra >= file) { +- if (parse_state == 0) { +- if (*ra == ':') { +- parse_state++; +- } else { +- break; +- } +- } else if (parse_state == 1) { +- if (*ra > '9' || *ra < '0') { +- char *opt_start = ra - strlen(RA_OPTSTR) + 1; +- if (opt_start > file && +- strncmp(opt_start, RA_OPTSTR, strlen(RA_OPTSTR)) == 0) { +- ra_val = ra + 1; +- ra -= strlen(RA_OPTSTR) - 1; +- *ra = '\0'; +- qdict_put(options, "readahead", qstring_from_str(ra_val)); +- } +- break; +- } +- } +- ra--; +- } +- +- qdict_put(options, "url", qstring_from_str(file)); +- +- g_free(file); ++ qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename)); + } + + static QemuOptsList runtime_opts = { +@@ -455,12 +422,12 @@ static QemuOptsList runtime_opts = { + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc = { + { +- .name = "url", ++ .name = CURL_BLOCK_OPT_URL, + .type = QEMU_OPT_STRING, + .help = "URL to open", + }, + { +- .name = "readahead", ++ .name = CURL_BLOCK_OPT_READAHEAD, + .type = QEMU_OPT_SIZE, + .help = "Readahead size", + }, +@@ -488,14 +455,15 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + goto out_noclean; + } + +- s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE); ++ s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, ++ READ_AHEAD_DEFAULT); + if ((s->readahead_size & 0x1ff) != 0) { + fprintf(stderr, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512\n", + s->readahead_size); + goto out_noclean; + } + +- file = qemu_opt_get(opts, "url"); ++ file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); + if (file == NULL) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "curl block driver requires " + "an 'url' option"); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Remove-erroneous-sleep-waiting-for-curl-complet.patch b/SOURCES/kvm-curl-Remove-erroneous-sleep-waiting-for-curl-complet.patch new file mode 100644 index 0000000..13f9958 --- /dev/null +++ b/SOURCES/kvm-curl-Remove-erroneous-sleep-waiting-for-curl-complet.patch @@ -0,0 +1,53 @@ +From 6313c97af86d08de7928433ab29ed4450f49c425 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:12 +0200 +Subject: [PATCH 12/30] curl: Remove erroneous sleep waiting for curl + completion + +Message-id: <1434022828-13037-6-git-send-email-rjones@redhat.com> +Patchwork-id: 65841 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 05/21] curl: Remove erroneous sleep waiting for curl completion +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +The driver will not start more than a fixed number of curl sessions. +If it needs more, it must wait for the completion of an existing one. +The driver was sleeping, which will prevent the main loop from +running, and therefore the event it's waiting on. It was also directly +calling its internal handler rather than waiting on existing +registered handlers to be called from the main loop. + +This change causes it simply to wait for a period of time whilst +allowing the main loop to execute. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: e466183718bfaaf347a3c02499473068a0072114 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 8c707e1..e06c222 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -289,8 +289,7 @@ static CURLState *curl_init_state(BDRVCURLState *s) + break; + } + if (!state) { +- g_usleep(100); +- curl_multi_do(s); ++ qemu_aio_wait(); + } + } while(!state); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Remove-unnecessary-explicit-calls-to-internal-e.patch b/SOURCES/kvm-curl-Remove-unnecessary-explicit-calls-to-internal-e.patch new file mode 100644 index 0000000..31433fb --- /dev/null +++ b/SOURCES/kvm-curl-Remove-unnecessary-explicit-calls-to-internal-e.patch @@ -0,0 +1,66 @@ +From 3ed5149c2375201051e0e8d38146dffaa0452fcd Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:15 +0200 +Subject: [PATCH 15/30] curl: Remove unnecessary explicit calls to internal + event handler + +Message-id: <1434022828-13037-9-git-send-email-rjones@redhat.com> +Patchwork-id: 65843 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 08/21] curl: Remove unnecessary explicit calls to internal event handler +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +Remove calls to curl_multi_do where the relevant handles are already +registered to the event loop. + +Ensure that we kick off socket handling with CURL_SOCKET_TIMEOUT after +adding a new handle. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: b69cdef876340624bb40a2054d14f298471a40a6 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index a6631fe..e4332c5 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -523,7 +523,6 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); + curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); + #endif +- curl_multi_do(s); + + qemu_opts_del(opts); + return 0; +@@ -567,6 +566,7 @@ static const AIOCBInfo curl_aiocb_info = { + static void curl_readv_bh_cb(void *p) + { + CURLState *state; ++ int running; + + CURLAIOCB *acb = p; + BDRVCURLState *s = acb->common.bs->opaque; +@@ -615,8 +615,9 @@ static void curl_readv_bh_cb(void *p) + curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); + + curl_multi_add_handle(s->multi, state->curl); +- curl_multi_do(s); + ++ /* Tell curl it needs to kick things off */ ++ curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); + } + + static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Remove-unnecessary-use-of-goto.patch b/SOURCES/kvm-curl-Remove-unnecessary-use-of-goto.patch new file mode 100644 index 0000000..adc9b07 --- /dev/null +++ b/SOURCES/kvm-curl-Remove-unnecessary-use-of-goto.patch @@ -0,0 +1,101 @@ +From d34f673f0d08eff0dce82db232574fe4b5e9ed95 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:10 +0200 +Subject: [PATCH 10/30] curl: Remove unnecessary use of goto + +Message-id: <1434022828-13037-4-git-send-email-rjones@redhat.com> +Patchwork-id: 65838 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 03/21] curl: Remove unnecessary use of goto +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Matthew Booth + +This isn't any of the usually acceptable uses of goto. + +Signed-off-by: Matthew Booth +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf + +Upstream-status: 9e550b326076caf4a1756b77eee95ad60b4adc27 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 55 +++++++++++++++++++++++++++---------------------------- + 1 file changed, 27 insertions(+), 28 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index f69e337..d399e3a 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -295,39 +295,38 @@ static CURLState *curl_init_state(BDRVCURLState *s) + } + } while(!state); + +- if (state->curl) +- goto has_curl; +- +- state->curl = curl_easy_init(); +- if (!state->curl) +- return NULL; +- curl_easy_setopt(state->curl, CURLOPT_URL, s->url); +- curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); +- curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_read_cb); +- curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); +- curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state); +- curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1); +- curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); +- curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); +- curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); +- curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); +- +- /* Restrict supported protocols to avoid security issues in the more +- * obscure protocols. For example, do not allow POP3/SMTP/IMAP see +- * CVE-2013-0249. +- * +- * Restricting protocols is only supported from 7.19.4 upwards. +- */ ++ if (!state->curl) { ++ state->curl = curl_easy_init(); ++ if (!state->curl) { ++ return NULL; ++ } ++ curl_easy_setopt(state->curl, CURLOPT_URL, s->url); ++ curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, 5); ++ curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, ++ (void *)curl_read_cb); ++ curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state); ++ curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state); ++ curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1); ++ curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1); ++ curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1); ++ curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg); ++ curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1); ++ ++ /* Restrict supported protocols to avoid security issues in the more ++ * obscure protocols. For example, do not allow POP3/SMTP/IMAP see ++ * CVE-2013-0249. ++ * ++ * Restricting protocols is only supported from 7.19.4 upwards. ++ */ + #if LIBCURL_VERSION_NUM >= 0x071304 +- curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS); +- curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS); ++ curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS); ++ curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS); + #endif + + #ifdef DEBUG_VERBOSE +- curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); ++ curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1); + #endif +- +-has_curl: ++ } + + state->s = s; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Replaced-old-error-handling-with-error-reportin.patch b/SOURCES/kvm-curl-Replaced-old-error-handling-with-error-reportin.patch new file mode 100644 index 0000000..a366198 --- /dev/null +++ b/SOURCES/kvm-curl-Replaced-old-error-handling-with-error-reportin.patch @@ -0,0 +1,42 @@ +From 7074c0e6d1de6b9861e176ea70a2f16cd7a93df1 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:08 +0200 +Subject: [PATCH 08/30] curl: Replaced old error handling with error reporting + API. + +Message-id: <1434022828-13037-2-git-send-email-rjones@redhat.com> +Patchwork-id: 65836 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 01/21] curl: Replaced old error handling with error reporting API. +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Maria Kustova + +Signed-off-by: Maria Kustova +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf + +Upstream-status: acd7fdc6d80711371d7a1507a22438d9465da63c) +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index b3d948e..a877dea 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -476,7 +476,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + return 0; + + out: +- fprintf(stderr, "CURL: Error opening file: %s\n", state->errmsg); ++ error_setg(errp, "CURL: Error opening file: %s", state->errmsg); + curl_easy_cleanup(state->curl); + state->curl = NULL; + out_noclean: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-The-macro-that-you-have-to-uncomment-to-get-deb.patch b/SOURCES/kvm-curl-The-macro-that-you-have-to-uncomment-to-get-deb.patch new file mode 100644 index 0000000..2329bda --- /dev/null +++ b/SOURCES/kvm-curl-The-macro-that-you-have-to-uncomment-to-get-deb.patch @@ -0,0 +1,41 @@ +From 65b21896d630af97cc50e24550516b3e76a30039 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:27 +0200 +Subject: [PATCH 27/30] curl: The macro that you have to uncomment to get + debugging is DEBUG_CURL. + +Message-id: <1434022828-13037-21-git-send-email-rjones@redhat.com> +Patchwork-id: 65855 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 20/21] curl: The macro that you have to uncomment to get debugging is DEBUG_CURL. +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: "Richard W.M. Jones" + +Signed-off-by: Richard W.M. Jones +Signed-off-by: Michael Tokarev + +Upstream-status: 41c2346716ff41df78062753128a87124f78ea29 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index ca881ee..5b407aa 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -26,7 +26,7 @@ + #include "qapi/qmp/qbool.h" + #include + +-// #define DEBUG ++// #define DEBUG_CURL + // #define DEBUG_VERBOSE + + #ifdef DEBUG_CURL +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Whitespace-only-changes.patch b/SOURCES/kvm-curl-Whitespace-only-changes.patch new file mode 100644 index 0000000..eb9c181 --- /dev/null +++ b/SOURCES/kvm-curl-Whitespace-only-changes.patch @@ -0,0 +1,44 @@ +From 5f3e36a4b2e3cc0591913778fcce9ee56f3292ac Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:13 +0200 +Subject: [PATCH 13/30] curl: Whitespace only changes. + +Message-id: <1434022828-13037-7-git-send-email-rjones@redhat.com> +Patchwork-id: 65840 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 06/21] curl: Whitespace only changes. +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: "Richard W.M. Jones" + +Trivial patch to remove odd whitespace. + +Signed-off-by: Richard W.M. Jones +Signed-off-by: Michael Tokarev + +Upstream-status: 9e5e2b23d301b1562677c6c115165eed6ce20a68 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index e06c222..7569dd5 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -466,8 +466,8 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + // initialize the multi interface! + + s->multi = curl_multi_init(); +- curl_multi_setopt( s->multi, CURLMOPT_SOCKETDATA, s); +- curl_multi_setopt( s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb ); ++ curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); ++ curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); + curl_multi_do(s); + + qemu_opts_del(opts); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-refuse-to-open-URL-from-HTTP-server-without-ran.patch b/SOURCES/kvm-curl-refuse-to-open-URL-from-HTTP-server-without-ran.patch new file mode 100644 index 0000000..731c1b8 --- /dev/null +++ b/SOURCES/kvm-curl-refuse-to-open-URL-from-HTTP-server-without-ran.patch @@ -0,0 +1,112 @@ +From cb2dd196bc247db6a40ea2847f86b63e9a923351 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Thu, 11 Jun 2015 11:40:21 +0200 +Subject: [PATCH 21/30] curl: refuse to open URL from HTTP server without range + support + +Message-id: <1434022828-13037-15-git-send-email-rjones@redhat.com> +Patchwork-id: 65849 +O-Subject: [RHEL-7.2 qemu-kvm v3 PATCH 14/21] curl: refuse to open URL from HTTP server without range support +Bugzilla: 1226684 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: Fam Zheng + +CURL driver requests partial data from server on guest IO req. For HTTP +and HTTPS, it uses "Range: ***" in requests, and this will not work if +server not accepting range. This patch does this check when open. + + * Removed curl_size_cb, which is not used: On one hand it's registered to + libcurl as CURLOPT_WRITEFUNCTION, instead of CURLOPT_HEADERFUNCTION, + which will get called with *data*, not *header*. On the other hand the + s->len is assigned unconditionally later. + + In this gone function, the sscanf for "Content-Length: %zd", on + (void *)ptr, which is not guaranteed to be zero-terminated, is + potentially a security bug. So this patch fixes it as a side-effect. The + bug is reported as: https://bugs.launchpad.net/qemu/+bug/1188943 + (Note the bug is marked "private" so you might not be able to see it) + + * Introduced curl_header_cb, which is used to parse header and mark the + server as accepting range if "Accept-Ranges: bytes" line is seen from + response header. If protocol is HTTP or HTTPS, but server response has + no not this support, refuse to open this URL. + +Note that python builtin module SimpleHTTPServer is an example of not +supporting range, if you need to test this driver, get a better server +or use internet URLs. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 3494d650273e619606c6cb2c38aa9b8b7bed98e2 +Signed-off-by: Miroslav Rezanina +--- + block/curl.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 67ea05f..e97682f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -106,6 +106,7 @@ typedef struct BDRVCURLState { + CURLState states[CURL_NUM_STATES]; + char *url; + size_t readahead_size; ++ bool accept_range; + } BDRVCURLState; + + static void curl_clean_state(CURLState *s); +@@ -157,14 +158,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + return 0; + } + +-static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque) ++static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + { +- CURLState *s = ((CURLState*)opaque); ++ BDRVCURLState *s = opaque; + size_t realsize = size * nmemb; +- size_t fsize; ++ const char *accept_line = "Accept-Ranges: bytes"; + +- if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) { +- s->s->len = fsize; ++ if (realsize >= strlen(accept_line) ++ && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { ++ s->accept_range = true; + } + + return realsize; +@@ -483,8 +485,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + + // Get file size + ++ s->accept_range = false; + curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); +- curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_size_cb); ++ curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, ++ curl_header_cb); ++ curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); + if (curl_easy_perform(state->curl)) + goto out; + curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); +@@ -494,6 +499,13 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags, + s->len = (size_t)d; + else if(!s->len) + goto out; ++ if ((!strncasecmp(s->url, "http://", strlen("http://")) ++ || !strncasecmp(s->url, "https://", strlen("https://"))) ++ && !s->accept_range) { ++ pstrcpy(state->errmsg, CURL_ERROR_SIZE, ++ "Server does not support 'range' (byte ranges)."); ++ goto out; ++ } + DPRINTF("CURL: Size = %zd\n", s->len); + + curl_clean_state(state); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch b/SOURCES/kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch index ff84ca7..af9d0b1 100644 --- a/SOURCES/kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch +++ b/SOURCES/kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch @@ -1,10 +1,16 @@ -From e3b51a8b94859d175b4733d3c17a960934f5edc6 Mon Sep 17 00:00:00 2001 +From ef9148789f335927506b9f86fe6805b764d57d27 Mon Sep 17 00:00:00 2001 From: Miroslav Rezanina -Date: Fri, 8 May 2015 17:40:22 +0200 -Subject: [PATCH] fdc: force the fifo access to be in bounds of the allocated - buffer +Date: Mon, 11 May 2015 10:13:23 +0200 +Subject: [PATCH 6/6] fdc: force the fifo access to be in bounds of the + allocated buffer -Bugzilla: 1219269 +Message-id: <1431332003-30588-1-git-send-email-mrezanin@redhat.com> +O-Subject: [RHEL-7.2 qemu-kvm EMBARGOED PATCH] fdc: force the fifo access + to be in bounds of the allocated buffer +Bugzilla: 1219270 +RH-Acked-by: Reviewed-by: Markus Armbruster +RH-Acked-by: Reviewed-by: Kevin Wolf +RH-Acked-by: Reviewed-by: Stefan Hajnoczi During processing of certain commands such as FD_CMD_READ_ID and FD_CMD_DRIVE_SPECIFICATION_COMMAND the fifo memory access could @@ -16,7 +22,7 @@ allocated memory. This is CVE-2015-3456. -Signed-off-by: Petr Matousek +Signed-off-by: Miroslav Rezanina --- hw/block/fdc.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/SOURCES/kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch b/SOURCES/kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch index a532e62..7ee00b4 100644 --- a/SOURCES/kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch +++ b/SOURCES/kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch @@ -1,7 +1,8 @@ -From 72e9da46b9dbbaa0e8d1ec332b876336df99e769 Mon Sep 17 00:00:00 2001 +From 5ba6a1889f6da826b7a3b16381977806d8efe553 Mon Sep 17 00:00:00 2001 From: Petr Matousek Date: Thu, 25 Jun 2015 12:46:37 +0200 -Subject: [PATCH] i8254: fix out-of-bounds memory access in pit_ioport_read() +Subject: [PATCH 01/10] i8254: fix out-of-bounds memory access in + pit_ioport_read() Message-id: <20150625124637.GJ18896@dhcp-25-225.brq.redhat.com> Patchwork-id: 66478 diff --git a/SOURCES/kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch b/SOURCES/kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch index abb9d13..3adae68 100644 --- a/SOURCES/kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch +++ b/SOURCES/kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch @@ -1,4 +1,4 @@ -From 892bb2a720de57109f7e8526879069abcaab38bf Mon Sep 17 00:00:00 2001 +From 03f2b3e5198471d80c3740450113643dff2109ce Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Jul 2015 16:15:58 +0200 Subject: [PATCH 1/3] ide: Check array bounds before writing to io_buffer @@ -8,7 +8,7 @@ Message-id: <1437056160-3284-2-git-send-email-kwolf@redhat.com> Patchwork-id: n/a O-Subject: [virt-devel] [RHEL/RHEV-7 qemu-kvm(-rhev) EMBARGOED PATCH 1/3] ide: Check array bounds before writing to io_buffer (CVE-2015-5154) -Bugzilla: 1243689 +Bugzilla: 1243690 RH-Acked-by: Petr Matousek RH-Acked-by: John Snow RH-Acked-by: Stefan Hajnoczi @@ -34,10 +34,10 @@ Signed-off-by: Kevin Wolf 1 file changed, 16 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c -index 24a1708..ada26c0 100644 +index d9fdb03..29bda6b 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c -@@ -1849,6 +1849,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) +@@ -1850,6 +1850,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) } p = s->data_ptr; @@ -48,7 +48,7 @@ index 24a1708..ada26c0 100644 *(uint16_t *)p = le16_to_cpu(val); p += 2; s->data_ptr = p; -@@ -1870,6 +1874,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr) +@@ -1871,6 +1875,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr) } p = s->data_ptr; @@ -59,7 +59,7 @@ index 24a1708..ada26c0 100644 ret = cpu_to_le16(*(uint16_t *)p); p += 2; s->data_ptr = p; -@@ -1891,6 +1899,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) +@@ -1892,6 +1900,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) } p = s->data_ptr; @@ -70,7 +70,7 @@ index 24a1708..ada26c0 100644 *(uint32_t *)p = le32_to_cpu(val); p += 4; s->data_ptr = p; -@@ -1912,6 +1924,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr) +@@ -1913,6 +1925,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr) } p = s->data_ptr; diff --git a/SOURCES/kvm-ide-Check-validity-of-logical-block-size.patch b/SOURCES/kvm-ide-Check-validity-of-logical-block-size.patch new file mode 100644 index 0000000..f35def6 --- /dev/null +++ b/SOURCES/kvm-ide-Check-validity-of-logical-block-size.patch @@ -0,0 +1,51 @@ +From e6e48f3e4e46ec72d85cfa663425ec820d438f5b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 12 Aug 2015 14:18:40 +0200 +Subject: [PATCH 2/2] ide: Check validity of logical block size + +Message-id: <1439389120-20473-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 67519 +O-Subject: [RHEL-7.2 qemu-kvm PATCH] ide: Check validity of logical block size +Bugzilla: 1134670 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi + +Our IDE emulation can't handle logical block sizes other than 512. Check +for it. + +The original assumption was that other values would silently be ignored +(which is bad enough), but it's not quite true: The physical block size +is exposed in IDENTIFY DEVICE as a multiple of the logical block size. +Setting a logical block size therefore also corrupts the physical block +size (4096/4096 doesn't silently downgrade to 4096/512, but 512/512). + +Signed-off-by: Kevin Wolf +Reviewed-by: Markus Armbruster +Reviewed-by: John Snow +(cherry picked from commit d20051856cd2fa8f10fed2d2a0b2751de5f7b20d) +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + hw/ide/qdev.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c +index 1d84e15..44f36c3 100644 +--- a/hw/ide/qdev.c ++++ b/hw/ide/qdev.c +@@ -159,6 +159,11 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) + return -1; + } + ++ if (dev->conf.logical_block_size != 512) { ++ error_report("logical_block_size must be 512 for IDE"); ++ return -1; ++ } ++ + blkconf_serial(&dev->conf, &dev->serial); + if (kind != IDE_CD + && blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch b/SOURCES/kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch index 0bf3fb4..79c5b7e 100644 --- a/SOURCES/kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch +++ b/SOURCES/kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch @@ -1,4 +1,4 @@ -From a6bc46fecbb3463447cd1e79afe60704afaa55e8 Mon Sep 17 00:00:00 2001 +From c887704e6425ee43d8b65e34dc0f57a4878231cf Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Jul 2015 16:16:00 +0200 Subject: [PATCH 3/3] ide: Clear DRQ after handling all expected accesses @@ -7,7 +7,7 @@ Message-id: <1437056160-3284-4-git-send-email-kwolf@redhat.com> Patchwork-id: n/a O-Subject: [virt-devel] [RHEL/RHEV-7 qemu-kvm(-rhev) EMBARGOED PATCH 3/3] ide: Clear DRQ after handling all expected accesses -Bugzilla: 1243689 +Bugzilla: 1243690 RH-Acked-by: Petr Matousek RH-Acked-by: John Snow RH-Acked-by: Stefan Hajnoczi @@ -24,10 +24,10 @@ Signed-off-by: Kevin Wolf 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c -index ada26c0..cd2e964 100644 +index 29bda6b..5d40093 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c -@@ -1856,8 +1856,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) +@@ -1857,8 +1857,10 @@ void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) *(uint16_t *)p = le16_to_cpu(val); p += 2; s->data_ptr = p; @@ -39,7 +39,7 @@ index ada26c0..cd2e964 100644 } uint32_t ide_data_readw(void *opaque, uint32_t addr) -@@ -1881,8 +1883,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr) +@@ -1882,8 +1884,10 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr) ret = cpu_to_le16(*(uint16_t *)p); p += 2; s->data_ptr = p; @@ -51,7 +51,7 @@ index ada26c0..cd2e964 100644 return ret; } -@@ -1906,8 +1910,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) +@@ -1907,8 +1911,10 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) *(uint32_t *)p = le32_to_cpu(val); p += 4; s->data_ptr = p; @@ -63,7 +63,7 @@ index ada26c0..cd2e964 100644 } uint32_t ide_data_readl(void *opaque, uint32_t addr) -@@ -1931,8 +1937,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr) +@@ -1932,8 +1938,10 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr) ret = cpu_to_le32(*(uint32_t *)p); p += 4; s->data_ptr = p; diff --git a/SOURCES/kvm-ide-Correct-handling-of-malformed-short-PRDTs.patch b/SOURCES/kvm-ide-Correct-handling-of-malformed-short-PRDTs.patch new file mode 100644 index 0000000..a766a1f --- /dev/null +++ b/SOURCES/kvm-ide-Correct-handling-of-malformed-short-PRDTs.patch @@ -0,0 +1,333 @@ +From 6a5797ecb4e557c746356a2f8636cceafa787851 Mon Sep 17 00:00:00 2001 +From: John Snow +Date: Fri, 26 Jun 2015 21:52:47 +0200 +Subject: [PATCH 2/2] ide: Correct handling of malformed/short PRDTs + +Message-id: <1435355567-29641-3-git-send-email-jsnow@redhat.com> +Patchwork-id: 66536 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] ide: Correct handling of malformed/short PRDTs +Bugzilla: 1205100 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Juan Quintela +RH-Acked-by: Stefan Hajnoczi + +This impacts both BMDMA and AHCI HBA interfaces for IDE. +Currently, we confuse the difference between a PRDT having +"0 bytes" and a PRDT having "0 complete sectors." + +When we receive an incomplete sector, inconsistent error checking +leads to an infinite loop wherein the call succeeds, but it +didn't give us enough bytes -- leading us to re-call the +DMA chain over and over again. This leads to, in the BMDMA case, +leaked memory for short PRDTs, and infinite loops and resource +usage in the AHCI case. + +The .prepare_buf() callback is reworked to return the number of +bytes that it successfully prepared. 0 is a valid, non-error +answer that means the table was empty and described no bytes. +-1 indicates an error. + +Our current implementation uses the io_buffer in IDEState to +ultimately describe the size of a prepared scatter-gather list. +Even though the AHCI PRDT/SGList can be as large as 256GiB, the +AHCI command header limits transactions to just 4GiB. ATA8-ACS3, +however, defines the largest transaction to be an LBA48 command +that transfers 65,536 sectors. With a 512 byte sector size, this +is just 32MiB. + +Since our current state structures use the int type to describe +the size of the buffer, and this state is migrated as int32, we +are limited to describing 2GiB buffer sizes unless we change the +migration protocol. + +For this reason, this patch begins to unify the assertions in the +IDE pathways that the scatter-gather list provided by either the +AHCI PRDT or the PCI BMDMA PRDs can only describe, at a maximum, +2GiB. This should be resilient enough unless we need a sector +size that exceeds 32KiB. + +Further, the likelihood of any guest operating system actually +attempting to transfer this much data in a single operation is +very slim. + +To this end, the IDEState variables have been updated to more +explicitly clarify our maximum supported size. Callers to the +prepare_buf callback have been reworked to understand the new +return code, and all versions of the prepare_buf callback have +been adjusted accordingly. + +Lastly, the ahci_populate_sglist helper, relied upon by the +AHCI implementation of .prepare_buf() as well as the PCI +implementation of the callback have had overflow assertions +added to help make clear the reasonings behind the various +type changes. + +[Added %d -> %"PRId64" fix John sent because off_pos changed from int to +int64_t. +--Stefan] + +Signed-off-by: John Snow +Reviewed-by: Paolo Bonzini +Message-id: 1414785819-26209-4-git-send-email-jsnow@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 3251bdcf1c67427d964517053c3d185b46e618e8) +Signed-off-by: John Snow +Signed-off-by: Miroslav Rezanina + +Conflicts: + hw/ide/ahci.c: Conflicts arising from not backporting bef1301ac + ahci: unify sglist preparation + hw/ide/core.c: Conflicts from not backporting IDEDMAOps changes, + including 9898586d8 and dependencies. + hw/ide/internal.h: Same as hw/ide/core.c. + hw/ide/macio.c: Conflicts from not backporting (many) IDEDMAOps + refactorings, 4aa3510f6 and others. + hw/ide/pci.c: Conflicts arising form not backporting f6c11d564 + ide: Introduce abstract QOM type for PCIIDEState + +Signed-off-by: John Snow +--- + hw/ide/ahci.c | 33 ++++++++++++++++++++++++++------- + hw/ide/core.c | 10 ++++++++-- + hw/ide/internal.h | 13 +++++++------ + hw/ide/pci.c | 26 +++++++++++++++++++++----- + 4 files changed, 62 insertions(+), 20 deletions(-) + +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index 7f3927a..e951ba0 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -640,7 +640,8 @@ static int prdt_tbl_entry_size(const AHCI_SG *tbl) + return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1; + } + +-static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) ++static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, ++ int32_t offset) + { + AHCICmdHdr *cmd = ad->cur_cmd; + uint32_t opts = le32_to_cpu(cmd->opts); +@@ -651,11 +652,19 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + uint8_t *prdt; + int i; + int r = 0; +- int sum = 0; ++ uint64_t sum = 0; + int off_idx = -1; +- int off_pos = -1; ++ int64_t off_pos = -1; + int tbl_entry_size; + ++ /* ++ * Note: AHCI PRDT can describe up to 256GiB. SATA/ATA only support ++ * transactions of up to 32MiB as of ATA8-ACS3 rev 1b, assuming a ++ * 512 byte sector size. We limit the PRDT in this implementation to ++ * a reasonably large 2GiB, which can accommodate the maximum transfer ++ * request for sector sizes up to 32K. ++ */ ++ + if (!sglist_alloc_hint) { + DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts); + return -1; +@@ -690,7 +699,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + } + if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) { + DPRINTF(ad->port_no, "%s: Incorrect offset! " +- "off_idx: %d, off_pos: %d\n", ++ "off_idx: %d, off_pos: %"PRId64"\n", + __func__, off_idx, off_pos); + r = -1; + goto out; +@@ -704,6 +713,13 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) + /* flags_size is zero-based */ + qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), + prdt_tbl_entry_size(&tbl[i])); ++ if (sglist->size > INT32_MAX) { ++ error_report("AHCI Physical Region Descriptor Table describes " ++ "more than 2 GiB.\n"); ++ qemu_sglist_destroy(sglist); ++ r = -1; ++ goto out; ++ } + } + } + +@@ -1047,16 +1063,19 @@ static void ahci_start_dma(IDEDMA *dma, IDEState *s, + dma_cb(s, 0); + } + +-static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write) ++static int32_t ahci_dma_prepare_buf(IDEDMA *dma, int is_write) + { + AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); + IDEState *s = &ad->port.ifs[0]; + +- ahci_populate_sglist(ad, &s->sg, 0); ++ if (ahci_populate_sglist(ad, &s->sg, 0) == -1) { ++ DPRINTF(ad->port_no, "ahci_dma_prepare_buf failed.\n"); ++ return -1; ++ } + s->io_buffer_size = s->sg.size; + + DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size); +- return s->io_buffer_size != 0; ++ return s->io_buffer_size; + } + + static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) +diff --git a/hw/ide/core.c b/hw/ide/core.c +index 9a22425..d9fdb03 100644 +--- a/hw/ide/core.c ++++ b/hw/ide/core.c +@@ -690,10 +690,11 @@ void ide_dma_cb(void *opaque, int ret) + n = s->nsector; + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; +- if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) == 0) { ++ if (s->bus->dma->ops->prepare_buf(s->bus->dma, ide_cmd_is_read(s)) < 512) { + /* The PRDs were too short. Reset the Active bit, but don't raise an + * interrupt. */ + s->status = READY_STAT | SEEK_STAT; ++ dma_buf_commit(s); + goto eot; + } + +@@ -2131,6 +2132,11 @@ static int ide_nop_int(IDEDMA *dma, int x) + return 0; + } + ++static int32_t ide_nop_int32(IDEDMA *dma, int x) ++{ ++ return 0; ++} ++ + static void ide_nop_restart(void *opaque, int x, RunState y) + { + } +@@ -2138,7 +2144,7 @@ static void ide_nop_restart(void *opaque, int x, RunState y) + static const IDEDMAOps ide_dma_nop_ops = { + .start_dma = ide_nop_start, + .start_transfer = ide_nop, +- .prepare_buf = ide_nop_int, ++ .prepare_buf = ide_nop_int32, + .rw_buf = ide_nop_int, + .set_unit = ide_nop_int, + .add_status = ide_nop_int, +diff --git a/hw/ide/internal.h b/hw/ide/internal.h +index 0a2d6bc..f8fb564 100644 +--- a/hw/ide/internal.h ++++ b/hw/ide/internal.h +@@ -323,6 +323,7 @@ typedef void EndTransferFunc(IDEState *); + typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); + typedef int DMAFunc(IDEDMA *); + typedef int DMAIntFunc(IDEDMA *, int); ++typedef int32_t DMAInt32Func(IDEDMA *, int); + typedef void DMARestartFunc(void *, int, RunState); + + struct unreported_events { +@@ -384,7 +385,7 @@ struct IDEState { + uint8_t cdrom_changed; + int packet_transfer_size; + int elementary_transfer_size; +- int io_buffer_index; ++ int32_t io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ +@@ -393,8 +394,8 @@ struct IDEState { + struct iovec iov; + QEMUIOVector qiov; + /* ATA DMA state */ +- int io_buffer_offset; +- int io_buffer_size; ++ int32_t io_buffer_offset; ++ int32_t io_buffer_size; + QEMUSGList sg; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ +@@ -404,8 +405,8 @@ struct IDEState { + uint8_t *io_buffer; + /* PIO save/restore */ + int32_t io_buffer_total_len; +- int cur_io_buffer_offset; +- int cur_io_buffer_len; ++ int32_t cur_io_buffer_offset; ++ int32_t cur_io_buffer_len; + uint8_t end_transfer_fn_idx; + QEMUTimer *sector_write_timer; /* only used for win2k install hack */ + uint32_t irq_count; /* counts IRQs when using win2k install hack */ +@@ -429,7 +430,7 @@ struct IDEState { + struct IDEDMAOps { + DMAStartFunc *start_dma; + DMAFunc *start_transfer; +- DMAIntFunc *prepare_buf; ++ DMAInt32Func *prepare_buf; + DMAIntFunc *rw_buf; + DMAIntFunc *set_unit; + DMAIntFunc *add_status; +diff --git a/hw/ide/pci.c b/hw/ide/pci.c +index cf7acb0..03b2081 100644 +--- a/hw/ide/pci.c ++++ b/hw/ide/pci.c +@@ -28,6 +28,7 @@ + #include + #include "block/block.h" + #include "sysemu/dma.h" ++#include "qemu/error-report.h" + + #include + +@@ -51,8 +52,11 @@ static void bmdma_start_dma(IDEDMA *dma, IDEState *s, + } + } + +-/* return 0 if buffer completed */ +-static int bmdma_prepare_buf(IDEDMA *dma, int is_write) ++/** ++ * Return the number of bytes successfully prepared. ++ * -1 on error. ++ */ ++static int32_t bmdma_prepare_buf(IDEDMA *dma, int is_write) + { + BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); + IDEState *s = bmdma_active_if(bm); +@@ -69,8 +73,9 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) + if (bm->cur_prd_len == 0) { + /* end of table (with a fail safe of one page) */ + if (bm->cur_prd_last || +- (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) +- return s->io_buffer_size != 0; ++ (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) { ++ return s->io_buffer_size; ++ } + pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8); + bm->cur_addr += 8; + prd.addr = le32_to_cpu(prd.addr); +@@ -85,12 +90,23 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) + l = bm->cur_prd_len; + if (l > 0) { + qemu_sglist_add(&s->sg, bm->cur_prd_addr, l); ++ ++ /* Note: We limit the max transfer to be 2GiB. ++ * This should accommodate the largest ATA transaction ++ * for LBA48 (65,536 sectors) and 32K sector sizes. */ ++ if (s->sg.size > INT32_MAX) { ++ error_report("IDE: sglist describes more than 2GiB.\n"); ++ break; ++ } + bm->cur_prd_addr += l; + bm->cur_prd_len -= l; + s->io_buffer_size += l; + } + } +- return 1; ++ ++ qemu_sglist_destroy(&s->sg); ++ s->io_buffer_size = 0; ++ return -1; + } + + /* return 0 if buffer completed */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch b/SOURCES/kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch index 1fa98c8..d690082 100644 --- a/SOURCES/kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch +++ b/SOURCES/kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch @@ -1,4 +1,4 @@ -From b4e9b91cce5952bb67a235490ad5f6bdb6b73ed5 Mon Sep 17 00:00:00 2001 +From cbc1dc59790015e0e86853ee523fed921ef6fe4e Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 16 Jul 2015 16:15:59 +0200 Subject: [PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion @@ -7,7 +7,7 @@ Message-id: <1437056160-3284-3-git-send-email-kwolf@redhat.com> Patchwork-id: n/a O-Subject: [virt-devel] [RHEL/RHEV-7 qemu-kvm(-rhev) EMBARGOED PATCH 2/3] ide/atapi: Fix START STOP UNIT command completion -Bugzilla: 1243689 +Bugzilla: 1243690 RH-Acked-by: Petr Matousek RH-Acked-by: John Snow RH-Acked-by: Stefan Hajnoczi @@ -21,10 +21,10 @@ Signed-off-by: Kevin Wolf 1 file changed, 1 insertion(+) diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c -index 05e60b1..f6d66a0 100644 +index 46a2c26..a411748 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c -@@ -879,6 +879,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) +@@ -896,6 +896,7 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) if (pwrcnd) { /* eject/load only happens for power condition == 0 */ diff --git a/SOURCES/kvm-iotests-Add-more-tests-for-qcow2-corruption.patch b/SOURCES/kvm-iotests-Add-more-tests-for-qcow2-corruption.patch new file mode 100644 index 0000000..597bbd2 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-more-tests-for-qcow2-corruption.patch @@ -0,0 +1,162 @@ +From 36dbb9edadf3cd22fd6f0da96cf293da35b0234c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:05 +0200 +Subject: [PATCH 11/42] iotests: Add more tests for qcow2 corruption + +Message-id: <1434212556-3927-12-git-send-email-mreitz@redhat.com> +Patchwork-id: 66030 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 11/42] iotests: Add more tests for qcow2 corruption +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Add tests for unaligned L1/L2/reftable entries and non-fatal corruption +reports. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-id: 1409926039-29044-6-git-send-email-mreitz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 5b0ed2be883238f52567ba2635ea38f34e8eb90d) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/060 | 56 ++++++++++++++++++++++++++++++++++++++++++++-- + tests/qemu-iotests/060.out | 51 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 105 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 +index 5180e23..e1187a3 100644 +--- a/tests/qemu-iotests/060 ++++ b/tests/qemu-iotests/060 +@@ -169,9 +169,61 @@ echo "=== Testing unallocated image header ===" + echo + _make_test_img 64M + # Create L1/L2 +-$QEMU_IO -c "$OPEN_RW" -c "write 0 64k" | _filter_qemu_io ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io + poke_file "$TEST_IMG" "$rb_offset" "\x00\x00" +-$QEMU_IO -c "$OPEN_RW" -c "write 64k 64k" | _filter_qemu_io ++$QEMU_IO -c "write 64k 64k" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing unaligned L1 entry ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++# This will be masked with ~(512 - 1) = ~0x1ff, so whether the lower 9 bits are ++# aligned or not does not matter ++poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x2a\x00" ++$QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing unaligned L2 entry ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00" ++$QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing unaligned reftable entry ===" ++echo ++_make_test_img 64M ++poke_file "$TEST_IMG" "$rt_offset" "\x00\x00\x00\x00\x00\x02\x2a\x00" ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing non-fatal corruption on freeing ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00" ++$QEMU_IO -c "discard 0 64k" "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo "=== Testing read-only corruption report ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00" ++# Should only emit a single error message ++$QEMU_IO -c "$OPEN_RO" -c "read 0 64k" -c "read 0 64k" | _filter_qemu_io ++ ++echo ++echo "=== Testing non-fatal and then fatal corruption report ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 128k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00" ++poke_file "$TEST_IMG" "$(($l2_offset+8))" "\x80\x00\x00\x00\x00\x06\x2a\x00" ++# Should emit two error messages ++$QEMU_IO -c "discard 0 64k" -c "read 64k 64k" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index 30806da..4f0c6d0 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -101,4 +101,55 @@ wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed + write failed: Input/output error ++ ++=== Testing unaligned L1 entry === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed ++read failed: Input/output error ++ ++=== Testing unaligned L2 entry === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed ++read failed: Input/output error ++ ++=== Testing unaligned reftable entry === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++qcow2: Marking image as corrupt: Refblock offset 0x22a00 unaligned (reftable index: 0); further corruption events will be suppressed ++write failed: Input/output error ++ ++=== Testing non-fatal corruption on freeing === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed ++discard 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing read-only corruption report === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Image is corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further non-fatal corruption events will be suppressed ++read failed: Input/output error ++read failed: Input/output error ++ ++=== Testing non-fatal and then fatal corruption report === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Image is corrupt: Cannot free unaligned cluster 0x52a00; further non-fatal corruption events will be suppressed ++qcow2: Marking image as corrupt: Data cluster offset 0x62a00 unaligned (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed ++discard 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read failed: Input/output error + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-test-for-image-header-overlap.patch b/SOURCES/kvm-iotests-Add-test-for-image-header-overlap.patch new file mode 100644 index 0000000..2341216 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-test-for-image-header-overlap.patch @@ -0,0 +1,70 @@ +From f65ef16bd01c14e252e262ec24ff3ac16e0e335d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:21:59 +0200 +Subject: [PATCH 05/42] iotests: Add test for image header overlap + +Message-id: <1434212556-3927-6-git-send-email-mreitz@redhat.com> +Patchwork-id: 66024 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 05/42] iotests: Add test for image header overlap +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Add a test for an image with an unallocated image header; instead of an +assertion, this should result in the image being marked corrupt. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit a42f8a3d05c5598cee893c9cf5ffeee48bacb83e) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/060 | 9 +++++++++ + tests/qemu-iotests/060.out | 8 ++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 +index 2abd566..5180e23 100644 +--- a/tests/qemu-iotests/060 ++++ b/tests/qemu-iotests/060 +@@ -164,6 +164,15 @@ wait_break 0 + write 64k 64k + resume 0" | $QEMU_IO | _filter_qemu_io + ++echo ++echo "=== Testing unallocated image header ===" ++echo ++_make_test_img 64M ++# Create L1/L2 ++$QEMU_IO -c "$OPEN_RW" -c "write 0 64k" | _filter_qemu_io ++poke_file "$TEST_IMG" "$rb_offset" "\x00\x00" ++$QEMU_IO -c "$OPEN_RW" -c "write 64k 64k" | _filter_qemu_io ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index a517948..c27c952 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -93,4 +93,12 @@ blkdebug: Suspended request '0' + write failed: Input/output error + blkdebug: Resuming request '0' + aio_write failed: No medium found ++ ++=== Testing unallocated image header === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Preventing invalid write on metadata (overlaps with qcow2_header); image marked as corrupt. ++write failed: Input/output error + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-test-for-non-existing-backing-file.patch b/SOURCES/kvm-iotests-Add-test-for-non-existing-backing-file.patch new file mode 100644 index 0000000..177cf17 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-test-for-non-existing-backing-file.patch @@ -0,0 +1,120 @@ +From f42cefd020d8fcd3a2b9ef2007af6fc473d628a5 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 22 Jul 2015 16:24:57 +0200 +Subject: [PATCH 5/5] iotests: Add test for non-existing backing file + +Message-id: <1437582297-9244-4-git-send-email-mreitz@redhat.com> +Patchwork-id: 67108 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/3] iotests: Add test for non-existing backing file +Bugzilla: 1238639 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng + +Test the error message when a COW file is about to be created which is +supposed to inherit the size of its backing file, while the backing file +given does not actually exist. + +Signed-off-by: Max Reitz +Reviewed-by: Kevin Wolf +Reviewed-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit c4d01535dcc2c6a573c03a85a9b7502d15f2bb45) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/111 | 53 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/111.out | 3 +++ + tests/qemu-iotests/group | 1 + + 3 files changed, 57 insertions(+) + create mode 100755 tests/qemu-iotests/111 + create mode 100644 tests/qemu-iotests/111.out + +diff --git a/tests/qemu-iotests/111 b/tests/qemu-iotests/111 +new file mode 100755 +index 0000000..6011c94 +--- /dev/null ++++ b/tests/qemu-iotests/111 +@@ -0,0 +1,53 @@ ++#!/bin/bash ++# ++# Test case for non-existing backing file when creating a qcow2 image ++# and not specifying the size ++# ++# Copyright (C) 2014 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=mreitz@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qed qcow qcow2 vmdk ++_supported_proto file ++_supported_os Linux ++_unsupported_imgopts "subformat=monolithicFlat" "subformat=twoGbMaxExtentFlat" ++ ++$QEMU_IMG create -f $IMGFMT -b "$TEST_IMG.inexistent" "$TEST_IMG" 2>&1 \ ++ | _filter_testdir | _filter_imgfmt ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/111.out b/tests/qemu-iotests/111.out +new file mode 100644 +index 0000000..683c01a +--- /dev/null ++++ b/tests/qemu-iotests/111.out +@@ -0,0 +1,3 @@ ++QA output created by 111 ++qemu-img: TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT.inexistent': No such file or directory ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 739c266..0644c42 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -88,6 +88,7 @@ + 105 rw auto quick + 107 rw auto quick + 108 rw auto quick ++111 rw auto quick + 114 rw auto quick + 121 rw auto + 130 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-test-for-potentially-damaging-repairs.patch b/SOURCES/kvm-iotests-Add-test-for-potentially-damaging-repairs.patch new file mode 100644 index 0000000..fe87798 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-test-for-potentially-damaging-repairs.patch @@ -0,0 +1,316 @@ +From de5dd97bab0923fdd8cd4ffebbbf3c031446030c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:25 +0200 +Subject: [PATCH 31/42] iotests: Add test for potentially damaging repairs + +Message-id: <1434212556-3927-32-git-send-email-mreitz@redhat.com> +Patchwork-id: 66050 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 31/42] iotests: Add test for potentially damaging repairs +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +There are certain cases where repairing a qcow2 image might actually +damage it further (or rather, where repairing it has in fact damaged it +further with the old qcow2 check implementation). This should not +happen, so add a test for these cases. + +Furthermore, the repair function now repairs refblocks beyond the image +end by resizing the image accordingly. Add several tests for this as +well. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 234764eed1aab56a657a161e9a0c65730442e6f8) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/108 | 141 +++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/108.out | 110 +++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 252 insertions(+) + create mode 100755 tests/qemu-iotests/108 + create mode 100644 tests/qemu-iotests/108.out + +diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108 +new file mode 100755 +index 0000000..12fc92a +--- /dev/null ++++ b/tests/qemu-iotests/108 +@@ -0,0 +1,141 @@ ++#!/bin/bash ++# ++# Test case for repairing qcow2 images which cannot be repaired using ++# the on-disk refcount structures ++# ++# Copyright (C) 2014 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=mreitz@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++# This tests qocw2-specific low-level functionality ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++ ++echo ++echo '=== Repairing an image without any refcount table ===' ++echo ++ ++_make_test_img 64M ++# just write some data ++$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io ++ ++# refcount_table_offset ++poke_file "$TEST_IMG" $((0x30)) "\x00\x00\x00\x00\x00\x00\x00\x00" ++# refcount_table_clusters ++poke_file "$TEST_IMG" $((0x38)) "\x00\x00\x00\x00" ++ ++_check_test_img -r all ++ ++$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo '=== Repairing unreferenced data cluster in new refblock area ===' ++echo ++ ++IMGOPTS='cluster_size=512' _make_test_img 64M ++# Allocate the first 128 kB in the image (first refblock) ++$QEMU_IO -c 'write 0 0x1b200' "$TEST_IMG" | _filter_qemu_io ++# should be 131072 == 0x20000 ++stat -c '%s' "$TEST_IMG" ++ ++# Enter a cluster at 128 kB (0x20000) ++# XXX: This should be the first free entry in the last L2 table, but we cannot ++# be certain ++poke_file "$TEST_IMG" $((0x1ccc8)) "\x80\x00\x00\x00\x00\x02\x00\x00" ++ ++# Fill the cluster ++truncate -s $((0x20200)) "$TEST_IMG" ++$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'write -P 42 128k 512' \ ++ | _filter_qemu_io ++ ++# The data should now appear at this guest offset ++$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io ++ ++# This cluster is unallocated; fix it ++_check_test_img -r all ++ ++# This repair operation must have allocated a new refblock; and that refblock ++# should not overlap with the unallocated data cluster. If it does, the data ++# will be damaged, so check it. ++$QEMU_IO -c 'read -P 42 0x1b200 512' "$TEST_IMG" | _filter_qemu_io ++ ++echo ++echo '=== Repairing refblock beyond the image end ===' ++echo ++ ++echo ++echo '--- Otherwise clean ---' ++echo ++ ++_make_test_img 64M ++# Normally, qemu doesn't create empty refblocks, so we just have to do it by ++# hand ++# XXX: This should be the entry for the second refblock ++poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" ++# Mark that refblock as used ++# XXX: This should be the 17th entry (cluster 16) of the first ++# refblock ++poke_file "$TEST_IMG" $((0x20020)) "\x00\x01" ++_check_test_img -r all ++ ++echo ++echo '--- Refblock is unallocated ---' ++echo ++ ++_make_test_img 64M ++poke_file "$TEST_IMG" $((0x10008)) "\x00\x00\x00\x00\x00\x10\x00\x00" ++_check_test_img -r all ++ ++echo ++echo '--- Signed overflow after the refblock ---' ++echo ++ ++_make_test_img 64M ++poke_file "$TEST_IMG" $((0x10008)) "\x7f\xff\xff\xff\xff\xff\x00\x00" ++_check_test_img -r all ++ ++echo ++echo '--- Unsigned overflow after the refblock ---' ++echo ++ ++_make_test_img 64M ++poke_file "$TEST_IMG" $((0x10008)) "\xff\xff\xff\xff\xff\xff\x00\x00" ++_check_test_img -r all ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out +new file mode 100644 +index 0000000..824d5cf +--- /dev/null ++++ b/tests/qemu-iotests/108.out +@@ -0,0 +1,110 @@ ++QA output created by 108 ++ ++=== Repairing an image without any refcount table === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ERROR cluster 0 refcount=0 reference=1 ++ERROR cluster 3 refcount=0 reference=1 ++ERROR cluster 4 refcount=0 reference=1 ++ERROR cluster 5 refcount=0 reference=1 ++Rebuilding refcount structure ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 4 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++read 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Repairing unreferenced data cluster in new refblock area === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 111104/111104 bytes at offset 0 ++108.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++131072 ++wrote 512/512 bytes at offset 131072 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 111104 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ERROR cluster 256 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 1 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++read 512/512 bytes at offset 111104 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Repairing refblock beyond the image end === ++ ++ ++--- Otherwise clean --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Repairing refcount block 1 is outside image ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 1 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++ ++--- Refblock is unallocated --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Repairing refcount block 1 is outside image ++ERROR cluster 16 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 ++Repairing cluster 16 refcount=1 reference=0 ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 2 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++ ++--- Signed overflow after the refblock --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Repairing refcount block 1 is outside image ++ERROR could not resize image: Invalid argument ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 1 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++ ++--- Unsigned overflow after the refblock --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++Repairing refcount block 1 is outside image ++ERROR could not resize image: Invalid argument ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 ++The following inconsistencies were found and repaired: ++ ++ 0 leaked clusters ++ 1 corruptions ++ ++Double checking the fixed image now... ++No errors were found on the image. ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index dd3c5fe..695ab02 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -87,3 +87,4 @@ + 092 rw auto quick + 105 rw auto quick + 107 rw auto quick ++108 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-test-for-qcow2-L1-table-update.patch b/SOURCES/kvm-iotests-Add-test-for-qcow2-L1-table-update.patch new file mode 100644 index 0000000..2ac40d2 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-test-for-qcow2-L1-table-update.patch @@ -0,0 +1,131 @@ +From 8c0c745cfd6e5e8e366449ed421edb250f24abf1 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:08 +0200 +Subject: [PATCH 14/42] iotests: Add test for qcow2 L1 table update + +Message-id: <1434212556-3927-15-git-send-email-mreitz@redhat.com> +Patchwork-id: 66033 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 14/42] iotests: Add test for qcow2 L1 table update +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Updating the L1 table should not result in random data being written. +This adds a test for that. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 1b2dd0bee6bd03045b90c8a7549c8134466b2938) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/107 | 61 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/107.out | 10 ++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 72 insertions(+) + create mode 100755 tests/qemu-iotests/107 + create mode 100644 tests/qemu-iotests/107.out + +diff --git a/tests/qemu-iotests/107 b/tests/qemu-iotests/107 +new file mode 100755 +index 0000000..cad1cf9 +--- /dev/null ++++ b/tests/qemu-iotests/107 +@@ -0,0 +1,61 @@ ++#!/bin/bash ++# ++# Tests updates of the qcow2 L1 table ++# ++# Copyright (C) 2014 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=mreitz@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++ ++ ++IMG_SIZE=64K ++ ++echo ++echo '=== Updates should not write random data ===' ++echo ++ ++_make_test_img $IMG_SIZE ++$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "open -o driver=raw $TEST_IMG" -c 'read -p -P 0 196616 65528' \ ++ | _filter_qemu_io ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 ++ +diff --git a/tests/qemu-iotests/107.out b/tests/qemu-iotests/107.out +new file mode 100644 +index 0000000..93445b7 +--- /dev/null ++++ b/tests/qemu-iotests/107.out +@@ -0,0 +1,10 @@ ++QA output created by 107 ++ ++=== Updates should not write random data === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 65528/65528 bytes at offset 196616 ++63.992 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index cd8384a..dd3c5fe 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -86,3 +86,4 @@ + 088 rw auto + 092 rw auto quick + 105 rw auto quick ++107 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-tests-for-more-corruption-cases.patch b/SOURCES/kvm-iotests-Add-tests-for-more-corruption-cases.patch new file mode 100644 index 0000000..af8b583 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-tests-for-more-corruption-cases.patch @@ -0,0 +1,94 @@ +From 39256a95ce8205edc697a21b0478047908cb440b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:32 +0200 +Subject: [PATCH 38/42] iotests: Add tests for more corruption cases + +Message-id: <1434212556-3927-39-git-send-email-mreitz@redhat.com> +Patchwork-id: 66057 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 38/42] iotests: Add tests for more corruption cases +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit f30136b35a271109b89353b9a5349cf32e6aeda7) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/060 | 15 +++++++++++++++ + tests/qemu-iotests/060.out | 13 +++++++++++++ + 2 files changed, 28 insertions(+) + +diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 +index e1187a3..ab44c83 100644 +--- a/tests/qemu-iotests/060 ++++ b/tests/qemu-iotests/060 +@@ -183,6 +183,12 @@ $QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io + poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x2a\x00" + $QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io + ++# Test how well zero cluster expansion can cope with this ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x2a\x00" ++$QEMU_IMG amend -o compat=0.10 "$TEST_IMG" ++ + echo + echo "=== Testing unaligned L2 entry ===" + echo +@@ -192,6 +198,15 @@ poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x00" + $QEMU_IO -c "read 0 64k" "$TEST_IMG" | _filter_qemu_io + + echo ++echo "=== Testing unaligned pre-allocated zero cluster ===" ++echo ++_make_test_img 64M ++$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x05\x2a\x01" ++# zero cluster expansion ++$QEMU_IMG amend -o compat=0.10 "$TEST_IMG" ++ ++echo + echo "=== Testing unaligned reftable entry ===" + echo + _make_test_img 64M +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index 88332e4..def7447 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -115,6 +115,11 @@ wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed + read failed: Input/output error ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Marking image as corrupt: L2 table offset 0x42a00 unaligned (L1 index: 0); further corruption events will be suppressed ++qemu-img: Error while amending options: Input/output error + + === Testing unaligned L2 entry === + +@@ -124,6 +129,14 @@ wrote 65536/65536 bytes at offset 0 + qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed + read failed: Input/output error + ++=== Testing unaligned pre-allocated zero cluster === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 65536/65536 bytes at offset 0 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++qcow2: Marking image as corrupt: Data cluster offset 0x52a00 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed ++qemu-img: Error while amending options: Input/output error ++ + === Testing unaligned reftable entry === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Add-tests-for-refcount-table-growth.patch b/SOURCES/kvm-iotests-Add-tests-for-refcount-table-growth.patch new file mode 100644 index 0000000..ff725b5 --- /dev/null +++ b/SOURCES/kvm-iotests-Add-tests-for-refcount-table-growth.patch @@ -0,0 +1,184 @@ +From 65d01862c82d46a2f440dab3818e8e08e6879551 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:34 +0200 +Subject: [PATCH 40/42] iotests: Add tests for refcount table growth + +Message-id: <1434212556-3927-41-git-send-email-mreitz@redhat.com> +Patchwork-id: 66059 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 40/42] iotests: Add tests for refcount table growth +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Signed-off-by: Max Reitz +Message-id: 1423598552-24301-3-git-send-email-mreitz@redhat.com +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +(cherry picked from commit 0e8a371468ce24513b15a9ae362f12822e1973a3) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/121 | 102 +++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/121.out | 23 ++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 126 insertions(+) + create mode 100755 tests/qemu-iotests/121 + create mode 100644 tests/qemu-iotests/121.out + +diff --git a/tests/qemu-iotests/121 b/tests/qemu-iotests/121 +new file mode 100755 +index 0000000..0912c3f +--- /dev/null ++++ b/tests/qemu-iotests/121 +@@ -0,0 +1,102 @@ ++#!/bin/bash ++# ++# Test cases for qcow2 refcount table growth ++# ++# Copyright (C) 2015 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=mreitz@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++ ++echo ++echo '=== New refcount structures may not conflict with existing structures ===' ++ ++echo ++echo '--- Test 1 ---' ++echo ++ ++# Preallocation speeds up the write operation, but preallocating everything will ++# destroy the purpose of the write; so preallocate one KB less than what would ++# cause a reftable growth... ++IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64512K ++# ...and make the image the desired size afterwards. ++$QEMU_IMG resize "$TEST_IMG" 65M ++ ++# The first write results in a growth of the refcount table during an allocation ++# which has precisely the required size so that the new refcount block allocated ++# in alloc_refcount_block() is right after cluster_index; this did lead to a ++# different refcount block being written to disk (a zeroed cluster) than what is ++# cached (a refblock with one entry having a refcount of 1), and the second ++# write would then result in that cached cluster being marked dirty and then ++# in it being written to disk. ++# This should not happen, the new refcount structures may not conflict with ++# new_block. ++# (Note that for some reason, 'write 63M 1K' does not trigger the problem) ++$QEMU_IO -c 'write 62M 1025K' -c 'write 64M 1M' "$TEST_IMG" | _filter_qemu_io ++ ++_check_test_img ++ ++ ++echo ++echo '--- Test 2 ---' ++echo ++ ++IMGOPTS='preallocation=metadata,cluster_size=1k' _make_test_img 64513K ++# This results in an L1 table growth which in turn results in some clusters at ++# the start of the image becoming free ++$QEMU_IMG resize "$TEST_IMG" 65M ++ ++# This write results in a refcount table growth; but the refblock allocated ++# immediately before that (new_block) takes cluster index 4 (which is now free) ++# and is thus not self-describing (in contrast to test 1, where new_block was ++# self-describing). The refcount table growth algorithm then used to place the ++# new refcount structures at cluster index 65536 (which is the same as the ++# cluster_index parameter in this case), allocating a new refcount block for ++# that cluster while new_block already existed, leaking new_block. ++# Therefore, the new refcount structures may not be put at cluster_index ++# (because new_block already describes that cluster, and the new structures try ++# to be self-describing). ++$QEMU_IO -c 'write 63M 130K' "$TEST_IMG" | _filter_qemu_io ++ ++_check_test_img ++ ++ ++# success, all done ++echo ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/121.out b/tests/qemu-iotests/121.out +new file mode 100644 +index 0000000..ff18e2c +--- /dev/null ++++ b/tests/qemu-iotests/121.out +@@ -0,0 +1,23 @@ ++QA output created by 121 ++ ++=== New refcount structures may not conflict with existing structures === ++ ++--- Test 1 --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66060288 preallocation='metadata' ++Image resized. ++wrote 1049600/1049600 bytes at offset 65011712 ++1.001 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 1048576/1048576 bytes at offset 67108864 ++1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++No errors were found on the image. ++ ++--- Test 2 --- ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66061312 preallocation='metadata' ++Image resized. ++wrote 133120/133120 bytes at offset 66060288 ++130 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++No errors were found on the image. ++ ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 5867cf7..dbb2a36 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -89,3 +89,4 @@ + 107 rw auto quick + 108 rw auto quick + 114 rw auto quick ++121 rw auto +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Fix-test-outputs.patch b/SOURCES/kvm-iotests-Fix-test-outputs.patch new file mode 100644 index 0000000..4924ecb --- /dev/null +++ b/SOURCES/kvm-iotests-Fix-test-outputs.patch @@ -0,0 +1,147 @@ +From 2e9f9fc69b25cd73b46750497f494d3ea28d21e6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:24 +0200 +Subject: [PATCH 30/42] iotests: Fix test outputs + +Message-id: <1434212556-3927-31-git-send-email-mreitz@redhat.com> +Patchwork-id: 66049 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 30/42] iotests: Fix test outputs +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +039, 060 and 061 all create images with referenced clusters having a +refcount of 0. Because previous commits changed handling of such errors, +these tests now have a different output. Fix it. + +Furthermore, 060 created a refblock with a refcount greater than one +which now results in having to rebuild the refcount structure as well. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit d26e6ec052b8768ab45654dbf35d5213818a2cb8) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/039.out | 10 ++++++++-- + tests/qemu-iotests/060.out | 10 ++++++++-- + tests/qemu-iotests/061.out | 18 ++++++++++++------ + 3 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out +index 077fa64..d25bf0b 100644 +--- a/tests/qemu-iotests/039.out ++++ b/tests/qemu-iotests/039.out +@@ -24,7 +24,10 @@ read 512/512 bytes at offset 0 + incompatible_features 0x1 + + == Repairing the image file must succeed == +-Repairing cluster 5 refcount=0 reference=1 ++ERROR cluster 5 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 + The following inconsistencies were found and repaired: + + 0 leaked clusters +@@ -43,7 +46,10 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 + wrote 512/512 bytes at offset 0 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + incompatible_features 0x1 +-Repairing cluster 5 refcount=0 reference=1 ++ERROR cluster 5 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 + wrote 512/512 bytes at offset 0 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + incompatible_features 0x0 +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index 4f0c6d0..88332e4 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -27,11 +27,15 @@ incompatible_features 0x0 + qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed + write failed: Input/output error + incompatible_features 0x2 +-Repairing refcount block 0 refcount=2 ++ERROR refcount block 0 refcount=2 ++ERROR cluster 2 refcount=1 reference=2 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=2 reference=1 + The following inconsistencies were found and repaired: + + 0 leaked clusters +- 1 corruptions ++ 2 corruptions + + Double checking the fixed image now... + No errors were found on the image. +@@ -59,6 +63,8 @@ incompatible_features 0x0 + qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed + write failed: Input/output error + incompatible_features 0x2 ++ERROR cluster 4 refcount=1 reference=2 ++Leaked cluster 9 refcount=1 reference=0 + Repairing cluster 4 refcount=1 reference=2 + Repairing cluster 9 refcount=1 reference=0 + Repairing OFLAG_COPIED data cluster: l2_entry=8000000000040000 refcount=2 +diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out +index 4027e00..c5127cf 100644 +--- a/tests/qemu-iotests/061.out ++++ b/tests/qemu-iotests/061.out +@@ -76,8 +76,11 @@ autoclear_features 0x0 + refcount_order 4 + header_length 104 + +-Repairing cluster 5 refcount=0 reference=1 +-Repairing cluster 6 refcount=0 reference=1 ++ERROR cluster 5 refcount=0 reference=1 ++ERROR cluster 6 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 + magic 0x514649fb + version 2 + backing_file_offset 0x0 +@@ -87,7 +90,7 @@ size 67108864 + crypt_method 0 + l1_size 1 + l1_table_offset 0x30000 +-refcount_table_offset 0x10000 ++refcount_table_offset 0x80000 + refcount_table_clusters 1 + nb_snapshots 0 + snapshot_offset 0x0 +@@ -230,8 +233,11 @@ autoclear_features 0x0 + refcount_order 4 + header_length 104 + +-Repairing cluster 5 refcount=0 reference=1 +-Repairing cluster 6 refcount=0 reference=1 ++ERROR cluster 5 refcount=0 reference=1 ++ERROR cluster 6 refcount=0 reference=1 ++Rebuilding refcount structure ++Repairing cluster 1 refcount=1 reference=0 ++Repairing cluster 2 refcount=1 reference=0 + magic 0x514649fb + version 3 + backing_file_offset 0x0 +@@ -241,7 +247,7 @@ size 67108864 + crypt_method 0 + l1_size 1 + l1_table_offset 0x30000 +-refcount_table_offset 0x10000 ++refcount_table_offset 0x80000 + refcount_table_clusters 1 + nb_snapshots 0 + snapshot_offset 0x0 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iscsi-Refuse-to-open-as-writable-if-the-LUN-is-write.patch b/SOURCES/kvm-iscsi-Refuse-to-open-as-writable-if-the-LUN-is-write.patch new file mode 100644 index 0000000..8fd957d --- /dev/null +++ b/SOURCES/kvm-iscsi-Refuse-to-open-as-writable-if-the-LUN-is-write.patch @@ -0,0 +1,103 @@ +From 8f412efbb8bb57fde0f924a7ad084f1c536c4a0b Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 20 Jan 2015 03:42:13 +0100 +Subject: [PATCH 06/16] iscsi: Refuse to open as writable if the LUN is write + protected + +Message-id: <1421725333-27072-1-git-send-email-famz@redhat.com> +Patchwork-id: 63370 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2] iscsi: Refuse to open as writable if the LUN is write protected +Bugzilla: 1032412 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +Before, when a write protected iSCSI target is attached as scsi-disk +with BDRV_O_RDWR, we report it as writable, while in fact all writes +will fail. + +One way to improve this is to report write protect flag as true to +guest, but a even better way is to refuse using a write protected LUN to +guest. + +Target write protect flag is checked with a mode sense query. + +Signed-off-by: Fam Zheng +Signed-off-by: Paolo Bonzini +(cherry picked from commit c1d4096b0f033d0a52c542f0948403783c3682e9) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/iscsi.c + +Trivial context conflict: AioContext attach/detach functions are not +present in downstream. +--- + block/iscsi.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +diff --git a/block/iscsi.c b/block/iscsi.c +index 4f42f29..3d61dd7 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1290,6 +1290,41 @@ fail: + return NULL; + } + ++ ++static bool iscsi_is_write_protected(IscsiLun *iscsilun) ++{ ++ struct scsi_task *task; ++ struct scsi_mode_sense *ms = NULL; ++ bool wrprotected = false; ++ ++ task = iscsi_modesense6_sync(iscsilun->iscsi, iscsilun->lun, ++ 1, SCSI_MODESENSE_PC_CURRENT, ++ 0x3F, 0, 255); ++ if (task == NULL) { ++ error_report("iSCSI: Failed to send MODE_SENSE(6) command: %s", ++ iscsi_get_error(iscsilun->iscsi)); ++ goto out; ++ } ++ ++ if (task->status != SCSI_STATUS_GOOD) { ++ error_report("iSCSI: Failed MODE_SENSE(6), LUN assumed writable"); ++ goto out; ++ } ++ ms = scsi_datain_unmarshall(task); ++ if (!ms) { ++ error_report("iSCSI: Failed to unmarshall MODE_SENSE(6) data: %s", ++ iscsi_get_error(iscsilun->iscsi)); ++ goto out; ++ } ++ wrprotected = ms->device_specific_parameter & 0x80; ++ ++out: ++ if (task) { ++ scsi_free_scsi_task(task); ++ } ++ return wrprotected; ++} ++ + /* + * We support iscsi url's on the form + * iscsi://[%@][:]// +@@ -1405,6 +1440,14 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, + scsi_free_scsi_task(task); + task = NULL; + ++ /* Check the write protect flag of the LUN if we want to write */ ++ if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) && ++ iscsi_is_write_protected(iscsilun)) { ++ error_setg(errp, "Cannot open a write protected LUN as read-write"); ++ ret = -EACCES; ++ goto out; ++ } ++ + iscsi_readcapacity_sync(iscsilun, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-main-set-current_machine-before-calling-machine-init.patch b/SOURCES/kvm-main-set-current_machine-before-calling-machine-init.patch new file mode 100644 index 0000000..f06964b --- /dev/null +++ b/SOURCES/kvm-main-set-current_machine-before-calling-machine-init.patch @@ -0,0 +1,67 @@ +From aec2ed0972eec0b7d251de1ae27de00b2bf29936 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 27 Jan 2015 17:48:10 +0100 +Subject: [PATCH 07/16] main(): set current_machine before calling + machine->init() + +Message-id: <1422380891-11054-2-git-send-email-lersek@redhat.com> +Patchwork-id: 63584 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] main(): set current_machine before calling machine->init() +Bugzilla: 1176283 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Vitaly Kuznetsov +RH-Acked-by: Markus Armbruster + +Performing the assignment earlier allows machine->init() and its children +to access current_machine->name. + +The alternative would be to pass QEMUMachineInitArgs down to +pc_memory_init() and even deeper, which I deem to cause more annoyance for +future backports than this patch. + +Note that upstream commit 0056ae24bc36798fdd96d0b31e217e9f73896736 moved +the assignment similarly (but it is not backportable to RHEL-7). + +This patch could only regress code that depends on the nullity of +"current_machine". I only found one such site, qemu_system_reset(). +qemu_system_reset() is called from the following places: +- load_vmstate(), which is not called in the code straddled by the + assignment movement, +- main_loop_should_exit(), ditto, +- later in main(), +- "xen-all.c", irrelevant. + +Downstream only. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +--- + vl.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/vl.c b/vl.c +index 2b3dc88..35b927e 100644 +--- a/vl.c ++++ b/vl.c +@@ -4252,6 +4252,9 @@ int main(int argc, char **argv, char **envp) + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, + .cpu_model = cpu_model }; ++ ++ current_machine = machine; ++ + machine->init(&args); + + audio_init(); +@@ -4260,8 +4263,6 @@ int main(int argc, char **argv, char **envp) + + set_numa_modes(); + +- current_machine = machine; +- + /* init USB devices */ + if (usb_enabled(false)) { + if (foreach_device_config(DEV_USB, usb_parse) < 0) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-mc146818rtc-add-rtc-reset-reinjection-QMP-command.patch b/SOURCES/kvm-mc146818rtc-add-rtc-reset-reinjection-QMP-command.patch new file mode 100644 index 0000000..4c349c5 --- /dev/null +++ b/SOURCES/kvm-mc146818rtc-add-rtc-reset-reinjection-QMP-command.patch @@ -0,0 +1,156 @@ +From 6fa144cedf0719b284355c9cd13ea6ec9a7c26d4 Mon Sep 17 00:00:00 2001 +From: Marcelo Tosatti +Date: Fri, 28 Aug 2015 01:07:55 +0200 +Subject: [PATCH] mc146818rtc: add rtc-reset-reinjection QMP command + +Message-id: <20150828010755.GA11313@amt.cnet> +Patchwork-id: 67629 +O-Subject: [RHEL-7.2 qemu-kvm PATCH] mc146818rtc: add rtc-reset-reinjection QMP command +Bugzilla: 1191226 +RH-Acked-by: Juan Quintela +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek + +Without this command libvirt refuses to allow guest agent +time synchronization to function. + +Upstream commit f2ae8abf1fa003e7ec6ee22cc3871924422a01d0 + +It is necessary to reset RTC interrupt reinjection backlog if +guest time is synchronized via a different mechanism, such as +QGA's guest-set-time command. + +Failing to do so causes both corrections to be applied (summed), +resulting in an incorrect guest time. + +Signed-off-by: Marcelo Tosatti +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Miroslav Rezanina +--- + hw/timer/mc146818rtc.c | 18 ++++++++++++++++++ + monitor.c | 7 +++++++ + qapi-schema.json | 13 +++++++++++++ + qmp-commands.hx | 23 +++++++++++++++++++++++ + 4 files changed, 61 insertions(+) + +diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c +index 432b16c..083f573 100644 +--- a/hw/timer/mc146818rtc.c ++++ b/hw/timer/mc146818rtc.c +@@ -26,6 +26,7 @@ + #include "sysemu/sysemu.h" + #include "hw/timer/mc146818rtc.h" + #include "qapi/visitor.h" ++#include "qmp-commands.h" + + #ifdef TARGET_I386 + #include "hw/i386/apic.h" +@@ -85,6 +86,7 @@ typedef struct RTCState { + Notifier clock_reset_notifier; + LostTickPolicy lost_tick_policy; + Notifier suspend_notifier; ++ QLIST_ENTRY(RTCState) link; + } RTCState; + + static void rtc_set_time(RTCState *s); +@@ -529,6 +531,20 @@ static void rtc_get_time(RTCState *s, struct tm *tm) + rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900; + } + ++static QLIST_HEAD(, RTCState) rtc_devices = ++ QLIST_HEAD_INITIALIZER(rtc_devices); ++ ++#ifdef TARGET_I386 ++void qmp_rtc_reset_reinjection(Error **errp) ++{ ++ RTCState *s; ++ ++ QLIST_FOREACH(s, &rtc_devices, link) { ++ s->irq_coalesced = 0; ++ } ++} ++#endif ++ + static void rtc_set_time(RTCState *s) + { + struct tm tm; +@@ -889,6 +905,8 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq) + } else { + isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ); + } ++ QLIST_INSERT_HEAD(&rtc_devices, s, link); ++ + return isadev; + } + +diff --git a/monitor.c b/monitor.c +index 798885d..6a1d06e 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -4878,3 +4878,10 @@ QemuOptsList qemu_mon_opts = { + { /* end of list */ } + }, + }; ++ ++#ifndef TARGET_I386 ++void qmp_rtc_reset_reinjection(Error **errp) ++{ ++ error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection"); ++} ++#endif +diff --git a/qapi-schema.json b/qapi-schema.json +index 8a7cf0b..c8732c1 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -4213,3 +4213,16 @@ + ## + { 'command': 'query-rx-filter', 'data': { '*name': 'str' }, + 'returns': ['RxFilterInfo'] } ++ ++## ++# @rtc-reset-reinjection ++# ++# This command will reset the RTC interrupt reinjection backlog. ++# Can be used if another mechanism to synchronize guest time ++# is in effect, for example QEMU guest agent's guest-set-time ++# command. ++# ++# Since: 2.1 ++## ++{ 'command': 'rtc-reset-reinjection' } ++ +diff --git a/qmp-commands.hx b/qmp-commands.hx +index 44dd48e..22a09be 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -3341,3 +3341,26 @@ Example: + } + + EQMP ++ ++#if defined TARGET_I386 ++ { ++ .name = "rtc-reset-reinjection", ++ .args_type = "", ++ .mhandler.cmd_new = qmp_marshal_input_rtc_reset_reinjection, ++ }, ++#endif ++ ++SQMP ++rtc-reset-reinjection ++--------------------- ++ ++Reset the RTC interrupt reinjection backlog. ++ ++Arguments: None. ++ ++Example: ++ ++-> { "execute": "rtc-reset-reinjection" } ++<- { "return": {} } ++ ++EQMP +-- +1.8.3.1 + diff --git a/SOURCES/kvm-migration_cancel-shutdown-migration-socket.patch b/SOURCES/kvm-migration_cancel-shutdown-migration-socket.patch new file mode 100644 index 0000000..5adc3e4 --- /dev/null +++ b/SOURCES/kvm-migration_cancel-shutdown-migration-socket.patch @@ -0,0 +1,64 @@ +From 8f6bbf90e819d271a62f2b59732d188b51a96128 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Fri, 16 Jan 2015 17:35:37 +0100 +Subject: [PATCH 05/16] migration_cancel: shutdown migration socket + +Message-id: <1421429737-23581-4-git-send-email-dgilbert@redhat.com> +Patchwork-id: 63334 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/3] migration_cancel: shutdown migration socket +Bugzilla: 1086168 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek + +From: "Dr. David Alan Gilbert" + +Force shutdown on migration socket on cancel to cause the cancel +to complete even if the socket is blocked on a dead network. + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Paolo Bonzini +Reviewed-by: Amit Shah +Signed-off-by: Amit Shah +(cherry picked from commit a26ba26e214911dc879a23e797d2c269cdb38577) +Signed-off-by: Miroslav Rezanina + +Conflicts: + migration.c +--- + migration.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/migration.c b/migration.c +index 44b993a..e8c5939 100644 +--- a/migration.c ++++ b/migration.c +@@ -331,6 +331,7 @@ void migrate_fd_error(MigrationState *s) + static void migrate_fd_cancel(MigrationState *s) + { + int old_state ; ++ QEMUFile *f = migrate_get_current()->file; + DPRINTF("cancelling migration\n"); + + do { +@@ -340,6 +341,17 @@ static void migrate_fd_cancel(MigrationState *s) + } + migrate_set_state(s, old_state, MIG_STATE_CANCELLING); + } while (s->state != MIG_STATE_CANCELLING); ++ ++ /* ++ * If we're unlucky the migration code might be stuck somewhere in a ++ * send/write while the network has failed and is waiting to timeout; ++ * if we've got shutdown(2) available then we can force it to quit. ++ * The outgoing qemu file gets closed in migrate_fd_cleanup that is ++ * called in a bh, so there is no race against this cancel. ++ */ ++ if (s->state == MIG_STATE_CANCELLING && f) { ++ qemu_file_shutdown(f); ++ } + } + + void add_migration_state_change_notifier(Notifier *notify) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc_sysfw-prevent-pflash-and-or-mis-sized-firmware-fo.patch b/SOURCES/kvm-pc_sysfw-prevent-pflash-and-or-mis-sized-firmware-fo.patch new file mode 100644 index 0000000..90e45f2 --- /dev/null +++ b/SOURCES/kvm-pc_sysfw-prevent-pflash-and-or-mis-sized-firmware-fo.patch @@ -0,0 +1,68 @@ +From c3f813d2f53fb8f9e2dc7e2b3c6b17d7fadb2de5 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Tue, 27 Jan 2015 17:48:11 +0100 +Subject: [PATCH 08/16] pc_sysfw: prevent pflash and/or mis-sized firmware for + rhel6.x.0 machtypes + +Message-id: <1422380891-11054-3-git-send-email-lersek@redhat.com> +Patchwork-id: 63585 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] pc_sysfw: prevent pflash and/or mis-sized firmware for rhel6.x.0 machtypes +Bugzilla: 1176283 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Vitaly Kuznetsov +RH-Acked-by: Markus Armbruster + +QE tried to boot OVMF on a rhel6.x.0 machine type. The shadow_bios() +migration hack that is in effect for those machine types is not compatible +with the OVMF image. An assert() in shadow_bios() catches it, but -- given +that OVMF has never been intended for rhel6.x.0 machine types -- QE has +rather requested us to deny such startups cleanly. + +The first hunk prevents "-M rhel6.x.0 -bios ..." style invocations where +the BIOS image is not 128 KB in size. This was suggested by Paolo and it +prevents the case when someone passes an OVMF binary via -bios. + +The second hunk prevents "-M rhel6.x.0 -pflash ...", since that +configuration (for boot firmware purposes or otherwise) was never +supported. + +Downstream only. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_sysfw.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index 6f5ecde..2f26ff5 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -191,6 +191,11 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) + (bios_size % 65536) != 0) { + goto bios_error; + } ++ if (shadow_bios_after_incoming && bios_size != 128 * 1024) { ++ error_report("machine %s only supports a 128KB BIOS image", ++ current_machine->name); ++ exit(1); ++ } + bios = g_malloc(sizeof(*bios)); + memory_region_init_ram(bios, "pc.bios", bios_size); + vmstate_register_ram_global(bios); +@@ -241,6 +246,12 @@ void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw) + return; + } + ++ if (shadow_bios_after_incoming) { ++ error_report("flash-based firmware is not supported by machine %s", ++ current_machine->name); ++ exit(1); ++ } ++ + if (kvm_enabled() && !kvm_readonly_mem_enabled()) { + /* Older KVM cannot execute from device memory. So, flash memory + * cannot be used unless the readonly memory kvm capability is present. */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qapi-block-Add-fatal-to-BLOCK_IMAGE_CORRUPTED.patch b/SOURCES/kvm-qapi-block-Add-fatal-to-BLOCK_IMAGE_CORRUPTED.patch new file mode 100644 index 0000000..682b4f8 --- /dev/null +++ b/SOURCES/kvm-qapi-block-Add-fatal-to-BLOCK_IMAGE_CORRUPTED.patch @@ -0,0 +1,83 @@ +From c13c12dd0abcb0e9800fa3a4769460067c0a5401 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:01 +0200 +Subject: [PATCH 07/42] qapi/block: Add "fatal" to BLOCK_IMAGE_CORRUPTED + +Message-id: <1434212556-3927-8-git-send-email-mreitz@redhat.com> +Patchwork-id: 66026 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 07/42] qapi/block: Add "fatal" to BLOCK_IMAGE_CORRUPTED +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Not every BLOCK_IMAGE_CORRUPTED event must be fatal; for example, when +reading from an image, they should generally not be. Nonetheless, even +an image only read from may of course be corrupted and this can be +detected during normal operation. In this case, a non-fatal event should +be emitted, but the image should not be marked corrupt (in accordance to +"fatal" set to false). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-id: 1409926039-29044-2-git-send-email-mreitz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 9bf040b962f90aa2e1cef6543dfee6c96f73ef7e) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2-refcount.c + qapi/block-core.json + QMP/qmp-events.txt + +Upstream, there is a more sophisticated QMP event support than just a +list of events in a text file. + +Signed-off-by: Max Reitz +--- + QMP/qmp-events.txt | 5 ++++- + block/qcow2-refcount.c | 4 ++-- + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt +index 7d16a6d..39daed4 100644 +--- a/QMP/qmp-events.txt ++++ b/QMP/qmp-events.txt +@@ -31,13 +31,16 @@ Data: + offset into the image (json-int) + - "size": If the corruption resulted from an image access, this is the access + size (json-int) ++- "fatal": If set, the image is marked corrupt and therefore unusable after ++ this event and must be repaired (Since 2.2; before, every ++ BLOCK_IMAGE_CORRUPTED event was fatal) + + Example: + + { "event": "BLOCK_IMAGE_CORRUPTED", + "data": { "device": "ide0-hd0", + "msg": "Prevented active L1 table overwrite", "offset": 196608, +- "size": 65536 }, ++ "size": 65536, "fatal": true }, + "timestamp": { "seconds": 1378126126, "microseconds": 966463 } } + + BLOCK_IO_ERROR +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 4f86923..6fa6daf 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1806,8 +1806,8 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, + message = g_strdup_printf("Prevented %s overwrite", + metadata_ol_names[metadata_ol_bitnr]); + data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'offset': %" +- PRId64 ", 'size': %" PRId64 " }", bs->device_name, message, +- offset, size); ++ PRId64 ", 'size': %" PRId64 ", 'fatal': true }", ++ bs->device_name, message, offset, size); + monitor_protocol_event(QEVENT_BLOCK_IMAGE_CORRUPTED, data); + g_free(message); + qobject_decref(data); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Add-qcow2_signal_corruption.patch b/SOURCES/kvm-qcow2-Add-qcow2_signal_corruption.patch new file mode 100644 index 0000000..6a56881 --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-qcow2_signal_corruption.patch @@ -0,0 +1,147 @@ +From f262d114ddfe11bad7b2f109cb965873f132f74e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:02 +0200 +Subject: [PATCH 08/42] qcow2: Add qcow2_signal_corruption() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-9-git-send-email-mreitz@redhat.com> +Patchwork-id: 66027 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 08/42] qcow2: Add qcow2_signal_corruption() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Add a helper function for easily marking an image corrupt (on fatal +corruptions) while outputting an informative message to stderr and via +QAPI. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Benoît Canet +Message-id: 1409926039-29044-3-git-send-email-mreitz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 85186ebdac7e183242deaa55d5049988de832be1) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2.c + +No qapi_event_send_*() downstream. + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 5 +++++ + 2 files changed, 67 insertions(+) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 6026f8a..be7e8e8 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -31,6 +31,8 @@ + #include "qapi/qmp/qerror.h" + #include "qapi/qmp/qbool.h" + #include "qapi/util.h" ++#include "qapi/qmp/types.h" ++#include "monitor/monitor.h" + #include "trace.h" + + /* +@@ -2329,6 +2331,66 @@ static int qcow2_amend_options(BlockDriverState *bs, + return 0; + } + ++/* ++ * If offset or size are negative, respectively, they will not be included in ++ * the BLOCK_IMAGE_CORRUPTED event emitted. ++ * fatal will be ignored for read-only BDS; corruptions found there will always ++ * be considered non-fatal. ++ */ ++void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, ++ int64_t size, const char *message_format, ...) ++{ ++ BDRVQcowState *s = bs->opaque; ++ char *message; ++ QObject *data; ++ va_list ap; ++ ++ fatal = fatal && !bs->read_only; ++ ++ if (s->signaled_corruption && ++ (!fatal || (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT))) ++ { ++ return; ++ } ++ ++ va_start(ap, message_format); ++ message = g_strdup_vprintf(message_format, ap); ++ va_end(ap); ++ ++ if (fatal) { ++ fprintf(stderr, "qcow2: Marking image as corrupt: %s; further " ++ "corruption events will be suppressed\n", message); ++ } else { ++ fprintf(stderr, "qcow2: Image is corrupt: %s; further non-fatal " ++ "corruption events will be suppressed\n", message); ++ } ++ ++ assert((offset >= 0) == (size >= 0)); ++ ++ if (offset >= 0) { ++ data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'offset': %" ++ PRId64 ", 'size': %" PRId64 ", 'fatal': %s }", ++ bdrv_get_device_name(bs), message, ++ offset, size, fatal ? "true" : "false"); ++ } else { ++ data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'fatal': %s }", ++ bdrv_get_device_name(bs), message, ++ fatal ? "true" : "false"); ++ } ++ ++ monitor_protocol_event(QEVENT_BLOCK_IMAGE_CORRUPTED, data); ++ qobject_decref(data); ++ ++ g_free(message); ++ ++ if (fatal) { ++ qcow2_mark_corrupt(bs); ++ bs->drv = NULL; /* make BDS unusable */ ++ } ++ ++ s->signaled_corruption = true; ++} ++ + static QEMUOptionParameter qcow2_create_options[] = { + { + .name = BLOCK_OPT_SIZE, +diff --git a/block/qcow2.h b/block/qcow2.h +index e958ab4..2138462 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -252,6 +252,7 @@ typedef struct BDRVQcowState { + bool discard_passthrough[QCOW2_DISCARD_MAX]; + + int overlap_check; /* bitmask of Qcow2MetadataOverlap values */ ++ bool signaled_corruption; + + uint64_t incompatible_features; + uint64_t compatible_features; +@@ -468,6 +469,10 @@ int qcow2_mark_corrupt(BlockDriverState *bs); + int qcow2_mark_consistent(BlockDriverState *bs); + int qcow2_update_header(BlockDriverState *bs); + ++void qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, ++ int64_t size, const char *message_format, ...) ++ GCC_FMT_ATTR(5, 6); ++ + /* qcow2-refcount.c functions */ + int qcow2_refcount_init(BlockDriverState *bs); + void qcow2_refcount_close(BlockDriverState *bs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Add-two-more-unalignment-checks.patch b/SOURCES/kvm-qcow2-Add-two-more-unalignment-checks.patch new file mode 100644 index 0000000..0734a10 --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-two-more-unalignment-checks.patch @@ -0,0 +1,72 @@ +From b8514c8dfe9af1d7c6e5ed3eff1a4383b5da087e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:31 +0200 +Subject: [PATCH 37/42] qcow2: Add two more unalignment checks + +Message-id: <1434212556-3927-38-git-send-email-mreitz@redhat.com> +Patchwork-id: 66056 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 37/42] qcow2: Add two more unalignment checks +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +This adds checks for unaligned L2 table offsets and unaligned data +cluster offsets (actually the preallocated offsets for zero clusters) to +the zero cluster expansion function. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 8dd93d9339505376f6ce6737ead871ff6d7e676f) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 053e9fe..f7938f6 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1579,6 +1579,14 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, + continue; + } + ++ if (offset_into_cluster(s, l2_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#" ++ PRIx64 " unaligned (L1 index: %#x)", ++ l2_offset, i); ++ ret = -EIO; ++ goto fail; ++ } ++ + if (is_active_l1) { + /* get active L2 tables from cache */ + ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, +@@ -1638,6 +1646,19 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table, + } + } + ++ if (offset_into_cluster(s, offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset " ++ "%#" PRIx64 " unaligned (L2 offset: %#" ++ PRIx64 ", L2 index: %#x)", offset, ++ l2_offset, j); ++ if (!preallocated) { ++ qcow2_free_clusters(bs, offset, s->cluster_size, ++ QCOW2_DISCARD_ALWAYS); ++ } ++ ret = -EIO; ++ goto fail; ++ } ++ + ret = qcow2_pre_write_overlap_check(bs, 0, offset, s->cluster_size); + if (ret < 0) { + if (!preallocated) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Calculate-refcount-block-entry-count.patch b/SOURCES/kvm-qcow2-Calculate-refcount-block-entry-count.patch new file mode 100644 index 0000000..4c07539 --- /dev/null +++ b/SOURCES/kvm-qcow2-Calculate-refcount-block-entry-count.patch @@ -0,0 +1,61 @@ +From 48ec01bf0d7ad38571741cf9aca816a0bfdddbe0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:10 +0200 +Subject: [PATCH 16/42] qcow2: Calculate refcount block entry count + +Message-id: <1434212556-3927-17-git-send-email-mreitz@redhat.com> +Patchwork-id: 66035 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 16/42] qcow2: Calculate refcount block entry count +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +The size of a refblock entry is (in theory) variable; calculate +therefore the number of entries per refblock and the according bit shift +(1 << x == entry count) when opening an image. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 1d13d654666a7fd6d6a85a0ce9285dbf0d0444c2) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 3 +++ + block/qcow2.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/block/qcow2.c b/block/qcow2.c +index be7e8e8..fae8b26 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -604,6 +604,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */ + s->l2_size = 1 << s->l2_bits; ++ /* 2^(s->refcount_order - 3) is the refcount width in bytes */ ++ s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3); ++ s->refcount_block_size = 1 << s->refcount_block_bits; + bs->total_sectors = header.size / 512; + s->csize_shift = (62 - (s->cluster_bits - 8)); + s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; +diff --git a/block/qcow2.h b/block/qcow2.h +index 2138462..b65f629 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -213,6 +213,8 @@ typedef struct BDRVQcowState { + int l2_size; + int l1_size; + int l1_vm_state_index; ++ int refcount_block_bits; ++ int refcount_block_size; + int csize_shift; + int csize_mask; + uint64_t cluster_offset_mask; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Catch-bdrv_getlength-error.patch b/SOURCES/kvm-qcow2-Catch-bdrv_getlength-error.patch new file mode 100644 index 0000000..bab6a0c --- /dev/null +++ b/SOURCES/kvm-qcow2-Catch-bdrv_getlength-error.patch @@ -0,0 +1,47 @@ +From 981daae137fd383944e72dbea8f147499eb9add4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:21:56 +0200 +Subject: [PATCH 02/42] qcow2: Catch bdrv_getlength() error + +Message-id: <1434212556-3927-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 66021 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 02/42] qcow2: Catch bdrv_getlength() error +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +The call to bdrv_getlength() from qcow2_check_refcounts() may result in +an error. Check this and abort if necessary. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit a49139af77850d64d74f9ffe43cabe7aa4f19de0) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 429b01c..4f86923 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1478,6 +1478,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + int ret; + + size = bdrv_getlength(bs->file); ++ if (size < 0) { ++ res->check_errors++; ++ return size; ++ } ++ + nb_clusters = size_to_clusters(s, size); + if (nb_clusters > INT_MAX) { + res->check_errors++; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Catch-host_offset-for-data-allocation.patch b/SOURCES/kvm-qcow2-Catch-host_offset-for-data-allocation.patch new file mode 100644 index 0000000..64205c3 --- /dev/null +++ b/SOURCES/kvm-qcow2-Catch-host_offset-for-data-allocation.patch @@ -0,0 +1,67 @@ +From cd10207e755b1b0470503c72c78a8d927f87a37a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:21:58 +0200 +Subject: [PATCH 04/42] qcow2: Catch !*host_offset for data allocation + +Message-id: <1434212556-3927-5-git-send-email-mreitz@redhat.com> +Patchwork-id: 66023 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 04/42] qcow2: Catch !*host_offset for data allocation +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +qcow2_alloc_cluster_offset() uses host_offset == 0 as "no preferred +offset" for the (data) cluster range to be allocated. However, this +offset is actually valid and may be allocated on images with a corrupted +refcount table or first refcount block. + +In this case, the corruption prevention should normally catch that +write anyway (because it would overwrite the image header). But since 0 +is a special value here, the function assumes that nothing has been +allocated at all which it asserts against. + +Because this condition is not qemu's fault but rather that of a broken +image, it shouldn't throw an assertion but rather mark the image corrupt +and show an appropriate message, which this patch does by calling the +corruption check earlier than it would be called normally (before the +assertion). + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit ff52aab2df5c5e10f231481961b88d25a3021724) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 1b9609f..f2f1170 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1089,6 +1089,17 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, + return 0; + } + ++ /* !*host_offset would overwrite the image header and is reserved for "no ++ * host offset preferred". If 0 was a valid host offset, it'd trigger the ++ * following overlap check; do that now to avoid having an invalid value in ++ * *host_offset. */ ++ if (!alloc_cluster_offset) { ++ ret = qcow2_pre_write_overlap_check(bs, 0, alloc_cluster_offset, ++ nb_clusters * s->cluster_size); ++ assert(ret < 0); ++ goto fail; ++ } ++ + /* + * Save info needed for meta data update. + * +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Check-L1-L2-reftable-entries-for-alignment.patch b/SOURCES/kvm-qcow2-Check-L1-L2-reftable-entries-for-alignment.patch new file mode 100644 index 0000000..0a1a940 --- /dev/null +++ b/SOURCES/kvm-qcow2-Check-L1-L2-reftable-entries-for-alignment.patch @@ -0,0 +1,215 @@ +From f48ffc234c0aa2017dc90c971bbb50d47362192b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:04 +0200 +Subject: [PATCH 10/42] qcow2: Check L1/L2/reftable entries for alignment + +Message-id: <1434212556-3927-11-git-send-email-mreitz@redhat.com> +Patchwork-id: 66029 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 10/42] qcow2: Check L1/L2/reftable entries for alignment +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Offsets taken from the L1, L2 and refcount tables are generally assumed +to be correctly aligned. However, this cannot be guaranteed if the image +has been written to by something different than qemu, thus check all +offsets taken from these tables for correct cluster alignment. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Message-id: 1409926039-29044-5-git-send-email-mreitz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit a97c67ee6c1546b985c1048c7a1f9e4fc13d9ee1) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 43 ++++++++++++++++++++++++++++++++++++++++--- + block/qcow2-refcount.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 82 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index f2f1170..0e3b8d7 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -459,6 +459,13 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, + goto out; + } + ++ if (offset_into_cluster(s, l2_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#" PRIx64 ++ " unaligned (L1 index: %#" PRIx64 ")", ++ l2_offset, l1_index); ++ return -EIO; ++ } ++ + /* load the l2 table in memory */ + + ret = l2_load(bs, l2_offset, &l2_table); +@@ -481,8 +488,11 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, + break; + case QCOW2_CLUSTER_ZERO: + if (s->qcow_version < 3) { +- qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); +- return -EIO; ++ qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found" ++ " in pre-v3 image (L2 offset: %#" PRIx64 ++ ", L2 index: %#x)", l2_offset, l2_index); ++ ret = -EIO; ++ goto fail; + } + c = count_contiguous_clusters(nb_clusters, s->cluster_size, + &l2_table[l2_index], 0, +@@ -500,6 +510,14 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, + &l2_table[l2_index], 0, + QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO); + *cluster_offset &= L2E_OFFSET_MASK; ++ if (offset_into_cluster(s, *cluster_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset %#" ++ PRIx64 " unaligned (L2 offset: %#" PRIx64 ++ ", L2 index: %#x)", *cluster_offset, ++ l2_offset, l2_index); ++ ret = -EIO; ++ goto fail; ++ } + break; + default: + abort(); +@@ -516,6 +534,10 @@ out: + *num = nb_available - index_in_cluster; + + return ret; ++ ++fail: ++ qcow2_cache_put(bs, s->l2_table_cache, (void **)&l2_table); ++ return ret; + } + + /* +@@ -551,6 +573,12 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, + + assert(l1_index < s->l1_size); + l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; ++ if (offset_into_cluster(s, l2_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#" PRIx64 ++ " unaligned (L1 index: %#" PRIx64 ")", ++ l2_offset, l1_index); ++ return -EIO; ++ } + + /* seek the l2 table of the given l2 offset */ + +@@ -918,6 +946,15 @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset, + bool offset_matches = + (cluster_offset & L2E_OFFSET_MASK) == *host_offset; + ++ if (offset_into_cluster(s, cluster_offset & L2E_OFFSET_MASK)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset " ++ "%#llx unaligned (guest offset: %#" PRIx64 ++ ")", cluster_offset & L2E_OFFSET_MASK, ++ guest_offset); ++ ret = -EIO; ++ goto out; ++ } ++ + if (*host_offset != 0 && !offset_matches) { + *bytes = 0; + ret = 0; +@@ -949,7 +986,7 @@ out: + + /* Only return a host offset if we actually made progress. Otherwise we + * would make requirements for handle_alloc() that it can't fulfill */ +- if (ret) { ++ if (ret > 0) { + *host_offset = (cluster_offset & L2E_OFFSET_MASK) + + offset_into_cluster(s, guest_offset); + } +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index dbcc4c6..e66d593 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -101,6 +101,13 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) + if (!refcount_block_offset) + return 0; + ++ if (offset_into_cluster(s, refcount_block_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Refblock offset %#" PRIx64 ++ " unaligned (reftable index: %#" PRIx64 ")", ++ refcount_block_offset, refcount_table_index); ++ return -EIO; ++ } ++ + ret = qcow2_cache_get(bs, s->refcount_block_cache, refcount_block_offset, + (void**) &refcount_block); + if (ret < 0) { +@@ -174,6 +181,14 @@ static int alloc_refcount_block(BlockDriverState *bs, + + /* If it's already there, we're done */ + if (refcount_block_offset) { ++ if (offset_into_cluster(s, refcount_block_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Refblock offset %#" ++ PRIx64 " unaligned (reftable index: " ++ "%#x)", refcount_block_offset, ++ refcount_table_index); ++ return -EIO; ++ } ++ + return load_refcount_block(bs, refcount_block_offset, + (void**) refcount_block); + } +@@ -812,8 +827,14 @@ void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_ZERO: + if (l2_entry & L2E_OFFSET_MASK) { +- qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, +- nb_clusters << s->cluster_bits, type); ++ if (offset_into_cluster(s, l2_entry & L2E_OFFSET_MASK)) { ++ qcow2_signal_corruption(bs, false, -1, -1, ++ "Cannot free unaligned cluster %#llx", ++ l2_entry & L2E_OFFSET_MASK); ++ } else { ++ qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, ++ nb_clusters << s->cluster_bits, type); ++ } + } + break; + case QCOW2_CLUSTER_UNALLOCATED: +@@ -872,6 +893,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + old_l2_offset = l2_offset; + l2_offset &= L1E_OFFSET_MASK; + ++ if (offset_into_cluster(s, l2_offset)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "L2 table offset %#" ++ PRIx64 " unaligned (L1 index: %#x)", ++ l2_offset, i); ++ ret = -EIO; ++ goto fail; ++ } ++ + ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset, + (void**) &l2_table); + if (ret < 0) { +@@ -905,6 +934,17 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + + case QCOW2_CLUSTER_NORMAL: + case QCOW2_CLUSTER_ZERO: ++ if (offset_into_cluster(s, offset & L2E_OFFSET_MASK)) { ++ qcow2_signal_corruption(bs, true, -1, -1, "Data " ++ "cluster offset %#llx " ++ "unaligned (L2 offset: %#" ++ PRIx64 ", L2 index: %#x)", ++ offset & L2E_OFFSET_MASK, ++ l2_offset, j); ++ ret = -EIO; ++ goto fail; ++ } ++ + cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits; + if (!cluster_index) { + /* unallocated */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Clean-up-after-refcount-rebuild.patch b/SOURCES/kvm-qcow2-Clean-up-after-refcount-rebuild.patch new file mode 100644 index 0000000..d335512 --- /dev/null +++ b/SOURCES/kvm-qcow2-Clean-up-after-refcount-rebuild.patch @@ -0,0 +1,94 @@ +From aa1df6fcd4c2dbfd39cac3e1d68208cca61643ce Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:23 +0200 +Subject: [PATCH 29/42] qcow2: Clean up after refcount rebuild + +Message-id: <1434212556-3927-30-git-send-email-mreitz@redhat.com> +Patchwork-id: 66048 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 29/42] qcow2: Clean up after refcount rebuild +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Because the old refcount structure will be leaked after having rebuilt +it, we need to recalculate the refcounts and run a leak-fixing operation +afterwards (if leaks should be fixed at all). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 791230d8bbd5c09d80845755a54074cd2d8b5a22) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 651ddb6..fe36bbd 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1983,12 +1983,57 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + nb_clusters); + + if (rebuild && (fix & BDRV_FIX_ERRORS)) { ++ BdrvCheckResult old_res = *res; ++ int fresh_leaks = 0; ++ + fprintf(stderr, "Rebuilding refcount structure\n"); + ret = rebuild_refcount_structure(bs, res, &refcount_table, + &nb_clusters); + if (ret < 0) { + goto fail; + } ++ ++ res->corruptions = 0; ++ res->leaks = 0; ++ ++ /* Because the old reftable has been exchanged for a new one the ++ * references have to be recalculated */ ++ rebuild = false; ++ memset(refcount_table, 0, nb_clusters * sizeof(uint16_t)); ++ ret = calculate_refcounts(bs, res, 0, &rebuild, &refcount_table, ++ &nb_clusters); ++ if (ret < 0) { ++ goto fail; ++ } ++ ++ if (fix & BDRV_FIX_LEAKS) { ++ /* The old refcount structures are now leaked, fix it; the result ++ * can be ignored, aside from leaks which were introduced by ++ * rebuild_refcount_structure() that could not be fixed */ ++ BdrvCheckResult saved_res = *res; ++ *res = (BdrvCheckResult){ 0 }; ++ ++ compare_refcounts(bs, res, BDRV_FIX_LEAKS, &rebuild, ++ &highest_cluster, refcount_table, nb_clusters); ++ if (rebuild) { ++ fprintf(stderr, "ERROR rebuilt refcount structure is still " ++ "broken\n"); ++ } ++ ++ /* Any leaks accounted for here were introduced by ++ * rebuild_refcount_structure() because that function has created a ++ * new refcount structure from scratch */ ++ fresh_leaks = res->leaks; ++ *res = saved_res; ++ } ++ ++ if (res->corruptions < old_res.corruptions) { ++ res->corruptions_fixed += old_res.corruptions - res->corruptions; ++ } ++ if (res->leaks < old_res.leaks) { ++ res->leaks_fixed += old_res.leaks - res->leaks; ++ } ++ res->leaks += fresh_leaks; + } else if (fix) { + if (rebuild) { + fprintf(stderr, "ERROR need to rebuild refcount structures\n"); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Discard-VM-state-in-active-L1-after-creating-s.patch b/SOURCES/kvm-qcow2-Discard-VM-state-in-active-L1-after-creating-s.patch new file mode 100644 index 0000000..7777aac --- /dev/null +++ b/SOURCES/kvm-qcow2-Discard-VM-state-in-active-L1-after-creating-s.patch @@ -0,0 +1,95 @@ +From 1ebfe2d9807a9ba4bfbec3104c6c8df50c89414d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 29 May 2015 17:05:12 +0200 +Subject: [PATCH 2/8] qcow2: Discard VM state in active L1 after creating + snapshot + +Message-id: <1432919112-18076-3-git-send-email-kwolf@redhat.com> +Patchwork-id: 65149 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] qcow2: Discard VM state in active L1 after creating snapshot +Bugzilla: 1208808 +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +During savevm, the VM state is written to the active L1 of the image and +then a snapshot is taken. After that, the VM state isn't needed any more +in the active L1 and should be discarded. This is implemented by this +patch. + +The impact of not discarding the VM state is that a snapshot can never +become smaller than any previous snapshot (because it would be padded +with old VM state), and more importantly that future savevm operations +cause unnecessary COWs (with associated flushes), which makes subsequent +snapshots much slower. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +(cherry picked from commit 1ebf561c11302f4fbe4afdd82758fe053cf1d5fc) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2.h + +Context-only conflict in qcow2.h. + +Signed-off-by: Kevin Wolf +--- + block/qcow2-snapshot.c | 7 +++++++ + block/qcow2.c | 5 ----- + block/qcow2.h | 5 +++++ + 3 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index 84481be..6081482 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -407,6 +407,13 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) + + g_free(old_snapshot_list); + ++ /* The VM state isn't needed any more in the active L1 table; in fact, it ++ * hurts by causing expensive COW for the next snapshot. */ ++ qcow2_discard_clusters(bs, qcow2_vm_state_offset(s), ++ align_offset(sn->vm_state_size, s->cluster_size) ++ >> BDRV_SECTOR_BITS, ++ QCOW2_DISCARD_NEVER); ++ + #ifdef DEBUG_ALLOC + { + BdrvCheckResult result = {0}; +diff --git a/block/qcow2.c b/block/qcow2.c +index babcb4b..6026f8a 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -2036,11 +2036,6 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs) + return 0; + } + +-static int64_t qcow2_vm_state_offset(BDRVQcowState *s) +-{ +- return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); +-} +- + static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) + { + BDRVQcowState *s = bs->opaque; +diff --git a/block/qcow2.h b/block/qcow2.h +index 9ad8aad..e958ab4 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -417,6 +417,11 @@ static inline int64_t align_offset(int64_t offset, int n) + return offset; + } + ++static inline int64_t qcow2_vm_state_offset(BDRVQcowState *s) ++{ ++ return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); ++} ++ + static inline uint64_t qcow2_max_refcount_clusters(BDRVQcowState *s) + { + return QCOW_MAX_REFTABLE_SIZE >> s->cluster_bits; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Do-not-overflow-when-writing-an-L1-sector.patch b/SOURCES/kvm-qcow2-Do-not-overflow-when-writing-an-L1-sector.patch new file mode 100644 index 0000000..182adb1 --- /dev/null +++ b/SOURCES/kvm-qcow2-Do-not-overflow-when-writing-an-L1-sector.patch @@ -0,0 +1,58 @@ +From 5cefc50d497d347c2352d785657b04db99e06ec8 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:07 +0200 +Subject: [PATCH 13/42] qcow2: Do not overflow when writing an L1 sector + +Message-id: <1434212556-3927-14-git-send-email-mreitz@redhat.com> +Patchwork-id: 66032 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 13/42] qcow2: Do not overflow when writing an L1 sector +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +While writing an L1 table sector, qcow2_write_l1_entry() copies the +respective range from s->l1_table to the local "buf" array. The size of +s->l1_table does not have to be a multiple of L1_ENTRIES_PER_SECTOR; +thus, limit the index which is used for copying all entries to the L1 +size. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: Peter Lieven +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit a1391444fe1cfef14976458f3293a2c6945e725c) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 0e3b8d7..053e9fe 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -151,12 +151,14 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, + int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) + { + BDRVQcowState *s = bs->opaque; +- uint64_t buf[L1_ENTRIES_PER_SECTOR]; ++ uint64_t buf[L1_ENTRIES_PER_SECTOR] = { 0 }; + int l1_start_index; + int i, ret; + + l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1); +- for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) { ++ for (i = 0; i < L1_ENTRIES_PER_SECTOR && l1_start_index + i < s->l1_size; ++ i++) ++ { + buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Do-not-perform-potentially-damaging-repairs.patch b/SOURCES/kvm-qcow2-Do-not-perform-potentially-damaging-repairs.patch new file mode 100644 index 0000000..a5e68d6 --- /dev/null +++ b/SOURCES/kvm-qcow2-Do-not-perform-potentially-damaging-repairs.patch @@ -0,0 +1,319 @@ +From 6745478978aed56c72daed821e912a9f9644932a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:21 +0200 +Subject: [PATCH 27/42] qcow2: Do not perform potentially damaging repairs + +Message-id: <1434212556-3927-28-git-send-email-mreitz@redhat.com> +Patchwork-id: 66046 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 27/42] qcow2: Do not perform potentially damaging repairs +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +If a referenced cluster has a refcount of 0, increasing its refcount may +result in clusters being allocated for the refcount structures. This may +overwrite the referenced cluster, therefore we cannot simply increase +the refcount then. + +In such cases, we can either try to replicate all the refcount +operations solely for the check operation, basing the allocations on the +in-memory refcount table; or we can simply rebuild the whole refcount +structure based on the in-memory refcount table. Since the latter will +be much easier, do that. + +To prepare for this, introduce a "rebuild" boolean which should be set +to true whenever a fix is rather dangerous or too complicated using the +current refcount structures. Another example for this is refcount blocks +being referenced more than once. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit f307b2558f61e068ce514f2dde2cad74c62036d6) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2-refcount.c + +Some conflicts in the code that is being removed. + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 186 +++++++------------------------------------------ + 1 file changed, 27 insertions(+), 159 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 8ce0447..3d66e7c 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1424,125 +1424,12 @@ fail: + } + + /* +- * Writes one sector of the refcount table to the disk +- */ +-#define RT_ENTRIES_PER_SECTOR (512 / sizeof(uint64_t)) +-static int write_reftable_entry(BlockDriverState *bs, int rt_index) +-{ +- BDRVQcowState *s = bs->opaque; +- uint64_t buf[RT_ENTRIES_PER_SECTOR]; +- int rt_start_index; +- int i, ret; +- +- rt_start_index = rt_index & ~(RT_ENTRIES_PER_SECTOR - 1); +- for (i = 0; i < RT_ENTRIES_PER_SECTOR; i++) { +- buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]); +- } +- +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_TABLE, +- s->refcount_table_offset + rt_start_index * sizeof(uint64_t), +- sizeof(buf)); +- if (ret < 0) { +- return ret; +- } +- +- BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_UPDATE); +- ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset + +- rt_start_index * sizeof(uint64_t), buf, sizeof(buf)); +- if (ret < 0) { +- return ret; +- } +- +- return 0; +-} +- +-/* +- * Allocates a new cluster for the given refcount block (represented by its +- * offset in the image file) and copies the current content there. This function +- * does _not_ decrement the reference count for the currently occupied cluster. +- * +- * This function prints an informative message to stderr on error (and returns +- * -errno); on success, 0 is returned. +- */ +-static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index, +- uint64_t offset) +-{ +- BDRVQcowState *s = bs->opaque; +- int64_t new_offset = 0; +- void *refcount_block = NULL; +- int ret; +- +- /* allocate new refcount block */ +- new_offset = qcow2_alloc_clusters(bs, s->cluster_size); +- if (new_offset < 0) { +- fprintf(stderr, "Could not allocate new cluster: %s\n", +- strerror(-new_offset)); +- ret = new_offset; +- goto fail; +- } +- +- /* fetch current refcount block content */ +- ret = qcow2_cache_get(bs, s->refcount_block_cache, offset, &refcount_block); +- if (ret < 0) { +- fprintf(stderr, "Could not fetch refcount block: %s\n", strerror(-ret)); +- goto fail; +- } +- +- /* new block has not yet been entered into refcount table, therefore it is +- * no refcount block yet (regarding this check) */ +- ret = qcow2_pre_write_overlap_check(bs, 0, new_offset, s->cluster_size); +- if (ret < 0) { +- fprintf(stderr, "Could not write refcount block; metadata overlap " +- "check failed: %s\n", strerror(-ret)); +- /* the image will be marked corrupt, so don't even attempt on freeing +- * the cluster */ +- new_offset = 0; +- goto fail; +- } +- +- /* write to new block */ +- ret = bdrv_write(bs->file, new_offset / BDRV_SECTOR_SIZE, refcount_block, +- s->cluster_sectors); +- if (ret < 0) { +- fprintf(stderr, "Could not write refcount block: %s\n", strerror(-ret)); +- goto fail; +- } +- +- /* update refcount table */ +- assert(!(new_offset & (s->cluster_size - 1))); +- s->refcount_table[reftable_index] = new_offset; +- ret = write_reftable_entry(bs, reftable_index); +- if (ret < 0) { +- fprintf(stderr, "Could not update refcount table: %s\n", +- strerror(-ret)); +- goto fail; +- } +- +-fail: +- if (new_offset && (ret < 0)) { +- qcow2_free_clusters(bs, new_offset, s->cluster_size, +- QCOW2_DISCARD_ALWAYS); +- } +- if (refcount_block) { +- if (ret < 0) { +- qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block); +- } else { +- ret = qcow2_cache_put(bs, s->refcount_block_cache, &refcount_block); +- } +- } +- if (ret < 0) { +- return ret; +- } +- return new_offset; +-} +- +-/* + * Checks consistency of refblocks and accounts for each refblock in + * *refcount_table. + */ + static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix, uint16_t **refcount_table, +- int64_t *nb_clusters) ++ BdrvCheckMode fix, bool *rebuild, ++ uint16_t **refcount_table, int64_t *nb_clusters) + { + BDRVQcowState *s = bs->opaque; + int64_t i, size; +@@ -1558,6 +1445,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + fprintf(stderr, "ERROR refcount block %" PRId64 " is not " + "cluster aligned; refcount table entry corrupted\n", i); + res->corruptions++; ++ *rebuild = true; + continue; + } + +@@ -1619,6 +1507,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + + resize_fail: + res->corruptions++; ++ *rebuild = true; + fprintf(stderr, "ERROR could not resize image: %s\n", + strerror(-ret)); + } else { +@@ -1634,43 +1523,10 @@ resize_fail: + return ret; + } + if ((*refcount_table)[cluster] != 1) { +- fprintf(stderr, "%s refcount block %" PRId64 +- " refcount=%d\n", +- fix & BDRV_FIX_ERRORS ? "Repairing" : +- "ERROR", +- i, (*refcount_table)[cluster]); +- +- if (fix & BDRV_FIX_ERRORS) { +- int64_t new_offset; +- +- new_offset = realloc_refcount_block(bs, i, offset); +- if (new_offset < 0) { +- res->corruptions++; +- continue; +- } +- +- /* update refcounts */ +- if ((new_offset >> s->cluster_bits) >= *nb_clusters) { +- /* increase refcount_table size if necessary */ +- int old_nb_clusters = *nb_clusters; +- *nb_clusters = (new_offset >> s->cluster_bits) + 1; +- *refcount_table = g_renew(uint16_t, *refcount_table, +- *nb_clusters); +- memset(&(*refcount_table)[old_nb_clusters], 0, +- (*nb_clusters - old_nb_clusters) * +- sizeof(**refcount_table)); +- } +- (*refcount_table)[cluster]--; +- ret = inc_refcounts(bs, res, refcount_table, nb_clusters, +- new_offset, s->cluster_size); +- if (ret < 0) { +- return ret; +- } +- +- res->corruptions_fixed++; +- } else { +- res->corruptions++; +- } ++ fprintf(stderr, "ERROR refcount block %" PRId64 ++ " refcount=%d\n", i, (*refcount_table)[cluster]); ++ res->corruptions++; ++ *rebuild = true; + } + } + } +@@ -1682,8 +1538,8 @@ resize_fail: + * Calculates an in-memory refcount table. + */ + static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix, uint16_t **refcount_table, +- int64_t *nb_clusters) ++ BdrvCheckMode fix, bool *rebuild, ++ uint16_t **refcount_table, int64_t *nb_clusters) + { + BDRVQcowState *s = bs->opaque; + int64_t i; +@@ -1735,7 +1591,7 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + return ret; + } + +- return check_refblocks(bs, res, fix, refcount_table, nb_clusters); ++ return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters); + } + + /* +@@ -1743,7 +1599,8 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + * refcount as reported by the refcount structures on-disk. + */ + static void compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix, int64_t *highest_cluster, ++ BdrvCheckMode fix, bool *rebuild, ++ int64_t *highest_cluster, + uint16_t *refcount_table, int64_t nb_clusters) + { + BDRVQcowState *s = bs->opaque; +@@ -1768,7 +1625,9 @@ static void compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + if (refcount1 != refcount2) { + /* Check if we're allowed to fix the mismatch */ + int *num_fixed = NULL; +- if (refcount1 > refcount2 && (fix & BDRV_FIX_LEAKS)) { ++ if (refcount1 == 0) { ++ *rebuild = true; ++ } else if (refcount1 > refcount2 && (fix & BDRV_FIX_LEAKS)) { + num_fixed = &res->leaks_fixed; + } else if (refcount1 < refcount2 && (fix & BDRV_FIX_ERRORS)) { + num_fixed = &res->corruptions_fixed; +@@ -1812,6 +1671,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + BDRVQcowState *s = bs->opaque; + int64_t size, highest_cluster, nb_clusters; + uint16_t *refcount_table = NULL; ++ bool rebuild = false; + int ret; + + size = bdrv_getlength(bs->file); +@@ -1829,14 +1689,22 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + res->bfi.total_clusters = + size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE); + +- ret = calculate_refcounts(bs, res, fix, &refcount_table, &nb_clusters); ++ ret = calculate_refcounts(bs, res, fix, &rebuild, &refcount_table, ++ &nb_clusters); + if (ret < 0) { + goto fail; + } + +- compare_refcounts(bs, res, fix, &highest_cluster, refcount_table, ++ compare_refcounts(bs, res, fix, &rebuild, &highest_cluster, refcount_table, + nb_clusters); + ++ if (rebuild) { ++ fprintf(stderr, "ERROR need to rebuild refcount structures\n"); ++ res->check_errors++; ++ /* Just carry on, the rest does not rely on the on-disk refcount ++ * structures */ ++ } ++ + /* check OFLAG_COPIED */ + ret = check_oflag_copied(bs, res, fix); + if (ret < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Drop-REFCOUNT_SHIFT.patch b/SOURCES/kvm-qcow2-Drop-REFCOUNT_SHIFT.patch new file mode 100644 index 0000000..c4bbe6c --- /dev/null +++ b/SOURCES/kvm-qcow2-Drop-REFCOUNT_SHIFT.patch @@ -0,0 +1,170 @@ +From 0b47923f65c2e457bb642b949f0e3dda722eba35 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:26 +0200 +Subject: [PATCH 32/42] qcow2: Drop REFCOUNT_SHIFT + +Message-id: <1434212556-3927-33-git-send-email-mreitz@redhat.com> +Patchwork-id: 66051 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 32/42] qcow2: Drop REFCOUNT_SHIFT +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +With BDRVQcowState.refcount_block_bits, we don't need REFCOUNT_SHIFT +anymore. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 17bd5f472754acd2458b53dc02a30d5651e6dd79) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 32 ++++++++++++++------------------ + block/qcow2.c | 2 +- + block/qcow2.h | 2 -- + 3 files changed, 15 insertions(+), 21 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index fe36bbd..87b932c 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -94,7 +94,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) + uint16_t *refcount_block; + uint16_t refcount; + +- refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); ++ refcount_table_index = cluster_index >> s->refcount_block_bits; + if (refcount_table_index >= s->refcount_table_size) + return 0; + refcount_block_offset = s->refcount_table[refcount_table_index]; +@@ -114,8 +114,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index) + return ret; + } + +- block_index = cluster_index & +- ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); ++ block_index = cluster_index & (s->refcount_block_size - 1); + refcount = be16_to_cpu(refcount_block[block_index]); + + ret = qcow2_cache_put(bs, s->refcount_block_cache, +@@ -150,8 +149,8 @@ static unsigned int next_refcount_table_size(BDRVQcowState *s, + static int in_same_refcount_block(BDRVQcowState *s, uint64_t offset_a, + uint64_t offset_b) + { +- uint64_t block_a = offset_a >> (2 * s->cluster_bits - REFCOUNT_SHIFT); +- uint64_t block_b = offset_b >> (2 * s->cluster_bits - REFCOUNT_SHIFT); ++ uint64_t block_a = offset_a >> (s->cluster_bits + s->refcount_block_bits); ++ uint64_t block_b = offset_b >> (s->cluster_bits + s->refcount_block_bits); + + return (block_a == block_b); + } +@@ -172,7 +171,7 @@ static int alloc_refcount_block(BlockDriverState *bs, + BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC); + + /* Find the refcount block for the given cluster */ +- refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); ++ refcount_table_index = cluster_index >> s->refcount_block_bits; + + if (refcount_table_index < s->refcount_table_size) { + +@@ -249,7 +248,7 @@ static int alloc_refcount_block(BlockDriverState *bs, + + /* The block describes itself, need to update the cache */ + int block_index = (new_block >> s->cluster_bits) & +- ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); ++ (s->refcount_block_size - 1); + (*refcount_block)[block_index] = cpu_to_be16(1); + } else { + /* Described somewhere else. This can recurse at most twice before we +@@ -321,8 +320,7 @@ static int alloc_refcount_block(BlockDriverState *bs, + BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW); + + /* Calculate the number of refcount blocks needed so far */ +- uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT); +- uint64_t blocks_used = DIV_ROUND_UP(cluster_index, refcount_block_clusters); ++ uint64_t blocks_used = DIV_ROUND_UP(cluster_index, s->refcount_block_size); + + if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { + return -EFBIG; +@@ -336,14 +334,14 @@ static int alloc_refcount_block(BlockDriverState *bs, + uint64_t table_clusters = + size_to_clusters(s, table_size * sizeof(uint64_t)); + blocks_clusters = 1 + +- ((table_clusters + refcount_block_clusters - 1) +- / refcount_block_clusters); ++ ((table_clusters + s->refcount_block_size - 1) ++ / s->refcount_block_size); + uint64_t meta_clusters = table_clusters + blocks_clusters; + + last_table_size = table_size; + table_size = next_refcount_table_size(s, blocks_used + +- ((meta_clusters + refcount_block_clusters - 1) +- / refcount_block_clusters)); ++ ((meta_clusters + s->refcount_block_size - 1) ++ / s->refcount_block_size)); + + } while (last_table_size != table_size); + +@@ -353,7 +351,7 @@ static int alloc_refcount_block(BlockDriverState *bs, + #endif + + /* Create the new refcount table and blocks */ +- uint64_t meta_offset = (blocks_used * refcount_block_clusters) * ++ uint64_t meta_offset = (blocks_used * s->refcount_block_size) * + s->cluster_size; + uint64_t table_offset = meta_offset + blocks_clusters * s->cluster_size; + uint16_t *new_blocks = g_malloc0(blocks_clusters * s->cluster_size); +@@ -545,8 +543,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + { + int block_index, refcount; + int64_t cluster_index = cluster_offset >> s->cluster_bits; +- int64_t table_index = +- cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); ++ int64_t table_index = cluster_index >> s->refcount_block_bits; + + /* Load the refcount block and allocate it if needed */ + if (table_index != old_table_index) { +@@ -568,8 +565,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + qcow2_cache_entry_mark_dirty(s->refcount_block_cache, refcount_block); + + /* we can update the count and save it */ +- block_index = cluster_index & +- ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); ++ block_index = cluster_index & (s->refcount_block_size - 1); + + refcount = be16_to_cpu(refcount_block[block_index]); + refcount += addend; +diff --git a/block/qcow2.c b/block/qcow2.c +index 6c3c6bc..4e60077 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1678,7 +1678,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + .l1_size = cpu_to_be32(0), + .refcount_table_offset = cpu_to_be64(cluster_size), + .refcount_table_clusters = cpu_to_be32(1), +- .refcount_order = cpu_to_be32(3 + REFCOUNT_SHIFT), ++ .refcount_order = cpu_to_be32(4), + .header_length = cpu_to_be32(sizeof(*header)), + }; + +diff --git a/block/qcow2.h b/block/qcow2.h +index b65f629..b210a7f 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -59,8 +59,6 @@ + /* The cluster reads as all zeros */ + #define QCOW_OFLAG_ZERO (1LL << 0) + +-#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ +- + #define MIN_CLUSTER_BITS 9 + #define MAX_CLUSTER_BITS 21 + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Fix-header-extension-size-check.patch b/SOURCES/kvm-qcow2-Fix-header-extension-size-check.patch new file mode 100644 index 0000000..3065313 --- /dev/null +++ b/SOURCES/kvm-qcow2-Fix-header-extension-size-check.patch @@ -0,0 +1,83 @@ +From 197c8b66cc0b7cc239075b4c86b0f118194e198a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:28 +0200 +Subject: [PATCH 34/42] qcow2: Fix header extension size check + +Message-id: <1434212556-3927-35-git-send-email-mreitz@redhat.com> +Patchwork-id: 66053 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 34/42] qcow2: Fix header extension size check +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +After reading the extension header, offset is incremented, but not +checked against end_offset any more. This way an integer overflow could +happen when checking whether the extension end is within the allowed +range, effectively disabling the check. + +This patch adds the missing check and a test case for it. + +Cc: qemu-stable@nongnu.org +Reported-by: Max Reitz +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Message-id: 1416935562-7760-2-git-send-email-kwolf@redhat.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 2ebafc854d109ff09b66fb4dd62c2c53fc29754a) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 2 +- + tests/qemu-iotests/080 | 2 ++ + tests/qemu-iotests/080.out | 2 ++ + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 4e60077..991c41f 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -116,7 +116,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + #ifdef DEBUG_EXT + printf("ext.magic = 0x%x\n", ext.magic); + #endif +- if (ext.len > end_offset - offset) { ++ if (offset > end_offset || ext.len > end_offset - offset) { + error_setg(errp, "Header extension too large"); + return -EINVAL; + } +diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080 +index 6b3a3e7..b9f9630 100755 +--- a/tests/qemu-iotests/080 ++++ b/tests/qemu-iotests/080 +@@ -78,6 +78,8 @@ poke_file "$TEST_IMG" "$offset_backing_file_offset" "\xff\xff\xff\xff\xff\xff\xf + poke_file "$TEST_IMG" "$offset_ext_magic" "\x12\x34\x56\x78" + poke_file "$TEST_IMG" "$offset_ext_size" "\x7f\xff\xff\xff" + { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x$(printf %x $offset_ext_size)" ++{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\x00\x00\x00\x00\x00" + { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + +diff --git a/tests/qemu-iotests/080.out b/tests/qemu-iotests/080.out +index 1fa0672..b7db555 100644 +--- a/tests/qemu-iotests/080.out ++++ b/tests/qemu-iotests/080.out +@@ -13,6 +13,8 @@ qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset + no file open, try 'help open' + qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large + no file open, try 'help open' ++qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large ++no file open, try 'help open' + + == Huge refcount table size == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Fix-header-update-with-overridden-backing-file.patch b/SOURCES/kvm-qcow2-Fix-header-update-with-overridden-backing-file.patch new file mode 100644 index 0000000..9c28213 --- /dev/null +++ b/SOURCES/kvm-qcow2-Fix-header-update-with-overridden-backing-file.patch @@ -0,0 +1,288 @@ +From 8538f7d5ace7b8ddb751d61a17c4a822b2333b39 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:35 +0200 +Subject: [PATCH 41/42] qcow2: Fix header update with overridden backing file + +Message-id: <1434212556-3927-42-git-send-email-mreitz@redhat.com> +Patchwork-id: 66060 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 41/42] qcow2: Fix header update with overridden backing file +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +In recent qemu versions, it is possible to override the backing file +name and format that is stored in the image file with values given at +runtime. In such cases, the temporary override could end up in the +image header if the qcow2 header was updated, while obviously correct +behaviour would be to leave the on-disk backing file path/format +unchanged. + +Fix this and add a test case for it. + +Reported-by: Michael Tokarev +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Message-id: 1428411796-2852-1-git-send-email-kwolf@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit e4603fe139e2161464d7e75faa3a650e31f057fc) +Signed-off-by: Miroslav Rezanina + +Conflicts: + tests/qemu-iotests/group + tests/qemu-iotests/130 + tests/qemu-iotests/130.out + +common.qemu does not exist downstream, so the HMP commit case cannot be +tested. _filter_img_info does not exist either, so just omit it and add +the additional cluster_size line to the test output (this test is +qcow2-specific anyway). + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 29 ++++++++++++++----- + block/qcow2.h | 6 ++++ + tests/qemu-iotests/130 | 71 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/130.out | 28 ++++++++++++++++++ + tests/qemu-iotests/group | 1 + + 5 files changed, 128 insertions(+), 7 deletions(-) + create mode 100755 tests/qemu-iotests/130 + create mode 100644 tests/qemu-iotests/130.out + +diff --git a/block/qcow2.c b/block/qcow2.c +index 991c41f..61f7e57 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -139,6 +139,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + return 3; + } + bs->backing_format[ext.len] = '\0'; ++ s->image_backing_format = g_strdup(bs->backing_format); + #ifdef DEBUG_EXT + printf("Qcow2: Got format extension %s\n", bs->backing_format); + #endif +@@ -734,6 +735,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + goto fail; + } + bs->backing_file[len] = '\0'; ++ s->image_backing_file = g_strdup(bs->backing_file); + } + + /* Internal snapshots */ +@@ -1249,6 +1251,9 @@ static void qcow2_close(BlockDriverState *bs) + g_free(s->unknown_header_fields); + cleanup_unknown_header_ext(bs); + ++ g_free(s->image_backing_file); ++ g_free(s->image_backing_format); ++ + g_free(s->cluster_cache); + qemu_vfree(s->cluster_data); + qcow2_refcount_close(bs); +@@ -1399,9 +1404,10 @@ int qcow2_update_header(BlockDriverState *bs) + } + + /* Backing file format header extension */ +- if (*bs->backing_format) { ++ if (s->image_backing_format) { + ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT, +- bs->backing_format, strlen(bs->backing_format), ++ s->image_backing_format, ++ strlen(s->image_backing_format), + buflen); + if (ret < 0) { + goto fail; +@@ -1459,8 +1465,8 @@ int qcow2_update_header(BlockDriverState *bs) + buflen -= ret; + + /* Backing file name */ +- if (*bs->backing_file) { +- size_t backing_file_len = strlen(bs->backing_file); ++ if (s->image_backing_file) { ++ size_t backing_file_len = strlen(s->image_backing_file); + + if (buflen < backing_file_len) { + ret = -ENOSPC; +@@ -1468,7 +1474,7 @@ int qcow2_update_header(BlockDriverState *bs) + } + + /* Using strncpy is ok here, since buf is not NUL-terminated. */ +- strncpy(buf, bs->backing_file, buflen); ++ strncpy(buf, s->image_backing_file, buflen); + + header->backing_file_offset = cpu_to_be64(buf - ((char*) header)); + header->backing_file_size = cpu_to_be32(backing_file_len); +@@ -1489,9 +1495,17 @@ fail: + static int qcow2_change_backing_file(BlockDriverState *bs, + const char *backing_file, const char *backing_fmt) + { ++ BDRVQcowState *s = bs->opaque; ++ + pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_file ?: ""); + pstrcpy(bs->backing_format, sizeof(bs->backing_format), backing_fmt ?: ""); + ++ g_free(s->image_backing_file); ++ g_free(s->image_backing_format); ++ ++ s->image_backing_file = backing_file ? g_strdup(bs->backing_file) : NULL; ++ s->image_backing_format = backing_fmt ? g_strdup(bs->backing_format) : NULL; ++ + return qcow2_update_header(bs); + } + +@@ -2286,8 +2300,9 @@ static int qcow2_amend_options(BlockDriverState *bs, + } + + if (backing_file || backing_format) { +- ret = qcow2_change_backing_file(bs, backing_file ?: bs->backing_file, +- backing_format ?: bs->backing_format); ++ ret = qcow2_change_backing_file(bs, ++ backing_file ?: s->image_backing_file, ++ backing_format ?: s->image_backing_format); + if (ret < 0) { + return ret; + } +diff --git a/block/qcow2.h b/block/qcow2.h +index b210a7f..dd3e768 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -263,6 +263,12 @@ typedef struct BDRVQcowState { + QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext; + QTAILQ_HEAD (, Qcow2DiscardRegion) discards; + bool cache_discards; ++ ++ /* Backing file path and format as stored in the image (this is not the ++ * effective path/format, which may be the result of a runtime option ++ * override) */ ++ char *image_backing_file; ++ char *image_backing_format; + } BDRVQcowState; + + /* XXX: use std qcow open function ? */ +diff --git a/tests/qemu-iotests/130 b/tests/qemu-iotests/130 +new file mode 100755 +index 0000000..68dbb48 +--- /dev/null ++++ b/tests/qemu-iotests/130 +@@ -0,0 +1,71 @@ ++#!/bin/bash ++# ++# Test that temporary backing file overrides (on the command line or in ++# blockdev-add) don't replace the original path stored in the image during ++# header updates. ++# ++# Copyright (C) 2015 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=kwolf@redhat.com ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++here="$PWD" ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto generic ++_supported_os Linux ++ ++ ++TEST_IMG="$TEST_IMG.orig" _make_test_img 64M ++TEST_IMG="$TEST_IMG.base" _make_test_img 64M ++_make_test_img 64M ++_img_info ++ ++echo ++echo "=== Marking image dirty (lazy refcounts) ===" ++echo ++ ++# Test that a backing file isn't written ++_make_test_img 64M ++$QEMU_IO -c "open -o backing.file.filename=$TEST_IMG.base,lazy-refcounts=on $TEST_IMG" -c "write 0 4k" | _filter_qemu_io ++_img_info ++ ++# Make sure that if there was a backing file that was just overridden on the ++# command line, that backing file is retained, with the right format ++_make_test_img -F raw -b "$TEST_IMG.orig" 64M ++$QEMU_IO -c "open -o backing.file.filename=$TEST_IMG.base,backing.driver=$IMGFMT,lazy-refcounts=on $TEST_IMG" -c "write 0 4k" | _filter_qemu_io ++_img_info ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/130.out b/tests/qemu-iotests/130.out +new file mode 100644 +index 0000000..bd489dd +--- /dev/null ++++ b/tests/qemu-iotests/130.out +@@ -0,0 +1,28 @@ ++QA output created by 130 ++Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 64M (67108864 bytes) ++cluster_size: 65536 ++ ++=== Marking image dirty (lazy refcounts) === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++wrote 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 64M (67108864 bytes) ++cluster_size: 65536 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.orig' backing_fmt='raw' ++wrote 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT ++virtual size: 64M (67108864 bytes) ++cluster_size: 65536 ++backing file: TEST_DIR/t.IMGFMT.orig ++backing file format: raw ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index dbb2a36..739c266 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -90,3 +90,4 @@ + 108 rw auto quick + 114 rw auto quick + 121 rw auto ++130 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Fix-leaks-in-dirty-images.patch b/SOURCES/kvm-qcow2-Fix-leaks-in-dirty-images.patch new file mode 100644 index 0000000..855408d --- /dev/null +++ b/SOURCES/kvm-qcow2-Fix-leaks-in-dirty-images.patch @@ -0,0 +1,50 @@ +From b8bdf32509624cb5a040ccc788028761db8d80eb Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:11 +0200 +Subject: [PATCH 17/42] qcow2: Fix leaks in dirty images +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-18-git-send-email-mreitz@redhat.com> +Patchwork-id: 66036 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 17/42] qcow2: Fix leaks in dirty images +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +When opening dirty images, qcow2's repair function should not only +repair errors but leaks as well. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Benoît Canet +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit 5b84106bd91bc67519738042c8890a09e2967513) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index fae8b26..6c3c6bc 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -764,7 +764,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + (s->incompatible_features & QCOW2_INCOMPAT_DIRTY)) { + BdrvCheckResult result = {0}; + +- ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS); ++ ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS | BDRV_FIX_LEAKS); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not repair dirty image"); + goto fail; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Fix-refcount-blocks-beyond-image-end.patch b/SOURCES/kvm-qcow2-Fix-refcount-blocks-beyond-image-end.patch new file mode 100644 index 0000000..8e03aec --- /dev/null +++ b/SOURCES/kvm-qcow2-Fix-refcount-blocks-beyond-image-end.patch @@ -0,0 +1,117 @@ +From 707d22d6fe9d2f43d0372472b62d40ddb652385d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:20 +0200 +Subject: [PATCH 26/42] qcow2: Fix refcount blocks beyond image end + +Message-id: <1434212556-3927-27-git-send-email-mreitz@redhat.com> +Patchwork-id: 66045 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 26/42] qcow2: Fix refcount blocks beyond image end +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +If the qcow2 check function detects a refcount block located beyond the +image end, grow the image appropriately. This cannot break anything and +is the logical fix for such a case. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 001c158defb65e88e6c50c85d6f20501f7149ddd) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 63 insertions(+), 4 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 8f1215c..8ce0447 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1545,7 +1545,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + int64_t *nb_clusters) + { + BDRVQcowState *s = bs->opaque; +- int64_t i; ++ int64_t i, size; + int ret; + + for(i = 0; i < s->refcount_table_size; i++) { +@@ -1562,9 +1562,68 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + if (cluster >= *nb_clusters) { +- fprintf(stderr, "ERROR refcount block %" PRId64 +- " is outside image\n", i); +- res->corruptions++; ++ fprintf(stderr, "%s refcount block %" PRId64 " is outside image\n", ++ fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i); ++ ++ if (fix & BDRV_FIX_ERRORS) { ++ int64_t old_nb_clusters = *nb_clusters; ++ uint16_t *new_refcount_table; ++ ++ if (offset > INT64_MAX - s->cluster_size) { ++ ret = -EINVAL; ++ goto resize_fail; ++ } ++ ++ ret = bdrv_truncate(bs->file, offset + s->cluster_size); ++ if (ret < 0) { ++ goto resize_fail; ++ } ++ size = bdrv_getlength(bs->file); ++ if (size < 0) { ++ ret = size; ++ goto resize_fail; ++ } ++ ++ *nb_clusters = size_to_clusters(s, size); ++ assert(*nb_clusters >= old_nb_clusters); ++ ++ new_refcount_table = g_try_realloc(*refcount_table, ++ *nb_clusters * ++ sizeof(**refcount_table)); ++ if (!new_refcount_table) { ++ *nb_clusters = old_nb_clusters; ++ res->check_errors++; ++ return -ENOMEM; ++ } ++ *refcount_table = new_refcount_table; ++ ++ memset(*refcount_table + old_nb_clusters, 0, ++ (*nb_clusters - old_nb_clusters) * ++ sizeof(**refcount_table)); ++ ++ if (cluster >= *nb_clusters) { ++ ret = -EINVAL; ++ goto resize_fail; ++ } ++ ++ res->corruptions_fixed++; ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, ++ offset, s->cluster_size); ++ if (ret < 0) { ++ return ret; ++ } ++ /* No need to check whether the refcount is now greater than 1: ++ * This area was just allocated and zeroed, so it can only be ++ * exactly 1 after inc_refcounts() */ ++ continue; ++ ++resize_fail: ++ res->corruptions++; ++ fprintf(stderr, "ERROR could not resize image: %s\n", ++ strerror(-ret)); ++ } else { ++ res->corruptions++; ++ } + continue; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Flush-pending-discards-before-allocating-clust.patch b/SOURCES/kvm-qcow2-Flush-pending-discards-before-allocating-clust.patch new file mode 100644 index 0000000..135e93e --- /dev/null +++ b/SOURCES/kvm-qcow2-Flush-pending-discards-before-allocating-clust.patch @@ -0,0 +1,61 @@ +From 1ae5408c46e940c7a993ba59c7e31163d78dd81a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:36 +0200 +Subject: [PATCH 42/42] qcow2: Flush pending discards before allocating cluster + +Message-id: <1434212556-3927-43-git-send-email-mreitz@redhat.com> +Patchwork-id: 66061 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 42/42] qcow2: Flush pending discards before allocating cluster +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +Before a freed cluster can be reused, pending discards for this cluster +must be processed. + +The original assumption was that this was not a problem because discards +are only cached during discard/write zeroes operations, which are +synchronous so that no concurrent write requests can cause cluster +allocations. + +However, the discard/write zeroes operation itself can allocate a new L2 +table (and it has to in order to put zero flags there), so make sure we +can cope with the situation. + +This fixes https://bugs.launchpad.net/bugs/1349972. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +(cherry picked from commit ecbda7a22576591a84f44de1be0150faf6001f1c) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index cee5b1f..848fd31 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -663,6 +663,11 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size) + uint64_t i, nb_clusters; + int refcount; + ++ /* We can't allocate clusters if they may still be queued for discard. */ ++ if (s->cache_discards) { ++ qcow2_process_discards(bs, 0); ++ } ++ + nb_clusters = size_to_clusters(s, size); + retry: + for(i = 0; i < nb_clusters; i++) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Let-inc_refcounts-resize-the-reftable.patch b/SOURCES/kvm-qcow2-Let-inc_refcounts-resize-the-reftable.patch new file mode 100644 index 0000000..63852f9 --- /dev/null +++ b/SOURCES/kvm-qcow2-Let-inc_refcounts-resize-the-reftable.patch @@ -0,0 +1,168 @@ +From f9a81072210afed390c21465ba973fc557105b79 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:18 +0200 +Subject: [PATCH 24/42] qcow2: Let inc_refcounts() resize the reftable + +Message-id: <1434212556-3927-25-git-send-email-mreitz@redhat.com> +Patchwork-id: 66043 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 24/42] qcow2: Let inc_refcounts() resize the reftable +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Now that the refcount table can be passed around by reference, do that +for inc_refcounts() (and subsequently check_refcounts_l1() and +check_refcounts_l2()) and use it for resizing it when a cluster after +the image end is encountered. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 641bb63cd6b003ab0ca2e312a014449037d71647) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 57 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 35 insertions(+), 22 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 4655fa2..7d03e65 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1055,8 +1055,8 @@ fail: + */ + static int inc_refcounts(BlockDriverState *bs, + BdrvCheckResult *res, +- uint16_t *refcount_table, +- int64_t refcount_table_size, ++ uint16_t **refcount_table, ++ int64_t *refcount_table_size, + int64_t offset, int64_t size) + { + BDRVQcowState *s = bs->opaque; +@@ -1071,17 +1071,30 @@ static int inc_refcounts(BlockDriverState *bs, + for(cluster_offset = start; cluster_offset <= last; + cluster_offset += s->cluster_size) { + k = cluster_offset >> s->cluster_bits; +- if (k >= refcount_table_size) { +- fprintf(stderr, "Warning: cluster offset=0x%" PRIx64 " is after " +- "the end of the image file, can't properly check refcounts.\n", +- cluster_offset); +- res->check_errors++; +- } else { +- if (++refcount_table[k] == 0) { +- fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64 +- "\n", cluster_offset); +- res->corruptions++; ++ if (k >= *refcount_table_size) { ++ int64_t old_refcount_table_size = *refcount_table_size; ++ uint16_t *new_refcount_table; ++ ++ *refcount_table_size = k + 1; ++ new_refcount_table = g_try_realloc(*refcount_table, ++ *refcount_table_size * ++ sizeof(**refcount_table)); ++ if (!new_refcount_table) { ++ *refcount_table_size = old_refcount_table_size; ++ res->check_errors++; ++ return -ENOMEM; + } ++ *refcount_table = new_refcount_table; ++ ++ memset(*refcount_table + old_refcount_table_size, 0, ++ (*refcount_table_size - old_refcount_table_size) * ++ sizeof(**refcount_table)); ++ } ++ ++ if (++(*refcount_table)[k] == 0) { ++ fprintf(stderr, "ERROR: overflow cluster offset=0x%" PRIx64 ++ "\n", cluster_offset); ++ res->corruptions++; + } + } + +@@ -1102,7 +1115,7 @@ enum { + * error occurred. + */ + static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, +- uint16_t *refcount_table, int64_t refcount_table_size, int64_t l2_offset, ++ uint16_t **refcount_table, int64_t *refcount_table_size, int64_t l2_offset, + int flags) + { + BDRVQcowState *s = bs->opaque; +@@ -1220,8 +1233,8 @@ fail: + */ + static int check_refcounts_l1(BlockDriverState *bs, + BdrvCheckResult *res, +- uint16_t *refcount_table, +- int64_t refcount_table_size, ++ uint16_t **refcount_table, ++ int64_t *refcount_table_size, + int64_t l1_table_offset, int l1_size, + int flags) + { +@@ -1556,7 +1569,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + if (offset != 0) { +- ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, + offset, s->cluster_size); + if (ret < 0) { + return ret; +@@ -1589,7 +1602,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + sizeof(**refcount_table)); + } + (*refcount_table)[cluster]--; +- ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, + new_offset, s->cluster_size); + if (ret < 0) { + return ret; +@@ -1625,14 +1638,14 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* header */ +- ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, + 0, s->cluster_size); + if (ret < 0) { + return ret; + } + + /* current L1 table */ +- ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, ++ ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, + s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); + if (ret < 0) { + return ret; +@@ -1641,20 +1654,20 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + /* snapshots */ + for (i = 0; i < s->nb_snapshots; i++) { + sn = s->snapshots + i; +- ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, ++ ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, + sn->l1_table_offset, sn->l1_size, 0); + if (ret < 0) { + return ret; + } + } +- ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, + s->snapshots_offset, s->snapshots_size); + if (ret < 0) { + return ret; + } + + /* refcount data */ +- ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ ret = inc_refcounts(bs, res, refcount_table, nb_clusters, + s->refcount_table_offset, + s->refcount_table_size * sizeof(uint64_t)); + if (ret < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Let-inc_refcounts-return-errno.patch b/SOURCES/kvm-qcow2-Let-inc_refcounts-return-errno.patch new file mode 100644 index 0000000..fe0a158 --- /dev/null +++ b/SOURCES/kvm-qcow2-Let-inc_refcounts-return-errno.patch @@ -0,0 +1,222 @@ +From 65ad32342584a286190e2ce56b8a3688f38f6535 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:17 +0200 +Subject: [PATCH 23/42] qcow2: Let inc_refcounts() return -errno + +Message-id: <1434212556-3927-24-git-send-email-mreitz@redhat.com> +Patchwork-id: 66042 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 23/42] qcow2: Let inc_refcounts() return -errno +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +As of a future patch, inc_refcounts() will have to throw errors which +are generally signaled by returning -errno. Therefore, let it return an +integer which is either 0 for success or -errno and handle the -errno +case in all callers. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit fef4d3d5644f984e9fa427dea4f7cfa15de9059c) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 91 +++++++++++++++++++++++++++++++++----------------- + 1 file changed, 60 insertions(+), 31 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 0dac4c9..4655fa2 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1053,17 +1053,18 @@ fail: + * + * Modifies the number of errors in res. + */ +-static void inc_refcounts(BlockDriverState *bs, +- BdrvCheckResult *res, +- uint16_t *refcount_table, +- int64_t refcount_table_size, +- int64_t offset, int64_t size) ++static int inc_refcounts(BlockDriverState *bs, ++ BdrvCheckResult *res, ++ uint16_t *refcount_table, ++ int64_t refcount_table_size, ++ int64_t offset, int64_t size) + { + BDRVQcowState *s = bs->opaque; + uint64_t start, last, cluster_offset, k; + +- if (size <= 0) +- return; ++ if (size <= 0) { ++ return 0; ++ } + + start = offset & ~(s->cluster_size - 1); + last = (offset + size - 1) & ~(s->cluster_size - 1); +@@ -1083,6 +1084,8 @@ static void inc_refcounts(BlockDriverState *bs, + } + } + } ++ ++ return 0; + } + + /* Flags for check_refcounts_l1() and check_refcounts_l2() */ +@@ -1137,8 +1140,11 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, + nb_csectors = ((l2_entry >> s->csize_shift) & + s->csize_mask) + 1; + l2_entry &= s->cluster_offset_mask; +- inc_refcounts(bs, res, refcount_table, refcount_table_size, +- l2_entry & ~511, nb_csectors * 512); ++ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, ++ l2_entry & ~511, nb_csectors * 512); ++ if (ret < 0) { ++ goto fail; ++ } + + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; +@@ -1173,8 +1179,11 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* Mark cluster as used */ +- inc_refcounts(bs, res, refcount_table,refcount_table_size, +- offset, s->cluster_size); ++ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, ++ offset, s->cluster_size); ++ if (ret < 0) { ++ goto fail; ++ } + + /* Correct offsets are cluster aligned */ + if (offset & (s->cluster_size - 1)) { +@@ -1217,19 +1226,20 @@ static int check_refcounts_l1(BlockDriverState *bs, + int flags) + { + BDRVQcowState *s = bs->opaque; +- uint64_t *l1_table, l2_offset, l1_size2; ++ uint64_t *l1_table = NULL, l2_offset, l1_size2; + int i, ret; + + l1_size2 = l1_size * sizeof(uint64_t); + + /* Mark L1 table as used */ +- inc_refcounts(bs, res, refcount_table, refcount_table_size, +- l1_table_offset, l1_size2); ++ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, ++ l1_table_offset, l1_size2); ++ if (ret < 0) { ++ goto fail; ++ } + + /* Read L1 table entries from disk */ +- if (l1_size2 == 0) { +- l1_table = NULL; +- } else { ++ if (l1_size2 > 0) { + l1_table = g_try_malloc(l1_size2); + if (l1_table == NULL) { + ret = -ENOMEM; +@@ -1252,8 +1262,11 @@ static int check_refcounts_l1(BlockDriverState *bs, + if (l2_offset) { + /* Mark L2 table as used */ + l2_offset &= L1E_OFFSET_MASK; +- inc_refcounts(bs, res, refcount_table, refcount_table_size, +- l2_offset, s->cluster_size); ++ ret = inc_refcounts(bs, res, refcount_table, refcount_table_size, ++ l2_offset, s->cluster_size); ++ if (ret < 0) { ++ goto fail; ++ } + + /* L2 tables are cluster aligned */ + if (l2_offset & (s->cluster_size - 1)) { +@@ -1520,6 +1533,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + { + BDRVQcowState *s = bs->opaque; + int64_t i; ++ int ret; + + for(i = 0; i < s->refcount_table_size; i++) { + uint64_t offset, cluster; +@@ -1542,8 +1556,11 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + if (offset != 0) { +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- offset, s->cluster_size); ++ ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ offset, s->cluster_size); ++ if (ret < 0) { ++ return ret; ++ } + if ((*refcount_table)[cluster] != 1) { + fprintf(stderr, "%s refcount block %" PRId64 + " refcount=%d\n", +@@ -1572,8 +1589,11 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + sizeof(**refcount_table)); + } + (*refcount_table)[cluster]--; +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- new_offset, s->cluster_size); ++ ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ new_offset, s->cluster_size); ++ if (ret < 0) { ++ return ret; ++ } + + res->corruptions_fixed++; + } else { +@@ -1605,8 +1625,11 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* header */ +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- 0, s->cluster_size); ++ ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ 0, s->cluster_size); ++ if (ret < 0) { ++ return ret; ++ } + + /* current L1 table */ + ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, +@@ -1619,18 +1642,24 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + for (i = 0; i < s->nb_snapshots; i++) { + sn = s->snapshots + i; + ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, +- sn->l1_table_offset, sn->l1_size, 0); ++ sn->l1_table_offset, sn->l1_size, 0); + if (ret < 0) { + return ret; + } + } +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- s->snapshots_offset, s->snapshots_size); ++ ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ s->snapshots_offset, s->snapshots_size); ++ if (ret < 0) { ++ return ret; ++ } + + /* refcount data */ +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- s->refcount_table_offset, +- s->refcount_table_size * sizeof(uint64_t)); ++ ret = inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ s->refcount_table_offset, ++ s->refcount_table_size * sizeof(uint64_t)); ++ if (ret < 0) { ++ return ret; ++ } + + return check_refblocks(bs, res, fix, refcount_table, nb_clusters); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Pass-discard-type-to-qcow2_discard_clusters.patch b/SOURCES/kvm-qcow2-Pass-discard-type-to-qcow2_discard_clusters.patch new file mode 100644 index 0000000..d855814 --- /dev/null +++ b/SOURCES/kvm-qcow2-Pass-discard-type-to-qcow2_discard_clusters.patch @@ -0,0 +1,96 @@ +From 4aec281092b790f6a91b657c6d6293171243a187 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 29 May 2015 17:05:11 +0200 +Subject: [PATCH 1/8] qcow2: Pass discard type to qcow2_discard_clusters() + +Message-id: <1432919112-18076-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 65148 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] qcow2: Pass discard type to qcow2_discard_clusters() +Bugzilla: 1208808 +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +The function will be used internally instead of only being called for +guest discard requests. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +(cherry picked from commit 670df5e3b4b5ef830a7c3c970170dbfa11cbb8d2) +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 8 ++++---- + block/qcow2.c | 2 +- + block/qcow2.h | 2 +- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 67f1393..81d90d9 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1333,7 +1333,7 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) + * clusters. + */ + static int discard_single_l2(BlockDriverState *bs, uint64_t offset, +- unsigned int nb_clusters) ++ unsigned int nb_clusters, enum qcow2_discard_type type) + { + BDRVQcowState *s = bs->opaque; + uint64_t *l2_table; +@@ -1362,7 +1362,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, + l2_table[l2_index + i] = cpu_to_be64(0); + + /* Then decrease the refcount */ +- qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); ++ qcow2_free_any_clusters(bs, old_offset, 1, type); + } + + ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); +@@ -1374,7 +1374,7 @@ static int discard_single_l2(BlockDriverState *bs, uint64_t offset, + } + + int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, +- int nb_sectors) ++ int nb_sectors, enum qcow2_discard_type type) + { + BDRVQcowState *s = bs->opaque; + uint64_t end_offset; +@@ -1397,7 +1397,7 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, + + /* Each L2 table is handled by its own loop iteration */ + while (nb_clusters > 0) { +- ret = discard_single_l2(bs, offset, nb_clusters); ++ ret = discard_single_l2(bs, offset, nb_clusters, type); + if (ret < 0) { + goto fail; + } +diff --git a/block/qcow2.c b/block/qcow2.c +index 005d513..babcb4b 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1870,7 +1870,7 @@ static coroutine_fn int qcow2_co_discard(BlockDriverState *bs, + + qemu_co_mutex_lock(&s->lock); + ret = qcow2_discard_clusters(bs, sector_num << BDRV_SECTOR_BITS, +- nb_sectors); ++ nb_sectors, QCOW2_DISCARD_REQUEST); + qemu_co_mutex_unlock(&s->lock); + return ret; + } +diff --git a/block/qcow2.h b/block/qcow2.h +index 1cc1ef0..9ad8aad 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -514,7 +514,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, + + int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); + int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, +- int nb_sectors); ++ int nb_sectors, enum qcow2_discard_type type); + int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors); + + int qcow2_expand_zero_clusters(BlockDriverState *bs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Pull-check_refblocks-up.patch b/SOURCES/kvm-qcow2-Pull-check_refblocks-up.patch new file mode 100644 index 0000000..658203f --- /dev/null +++ b/SOURCES/kvm-qcow2-Pull-check_refblocks-up.patch @@ -0,0 +1,156 @@ +From 0a8f6084033d307f4e60104be1da0da99e8775b6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:14 +0200 +Subject: [PATCH 20/42] qcow2: Pull check_refblocks() up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-21-git-send-email-mreitz@redhat.com> +Patchwork-id: 66039 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 20/42] qcow2: Pull check_refblocks() up +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Pull check_refblocks() before calculate_refcounts() so we can drop its +static declaration. + +Signed-off-by: Max Reitz +Reviewed-by: Benoît Canet +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit 057a3fe57e740e5e1cc3d62c9b8e0085e9fffa74) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 102 ++++++++++++++++++++++++------------------------- + 1 file changed, 49 insertions(+), 53 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index cb78f05..0d10865 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1501,59 +1501,6 @@ fail: + return new_offset; + } + +-static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix, uint16_t **refcount_table, +- int64_t *nb_clusters); +- +-/* +- * Calculates an in-memory refcount table. +- */ +-static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix, uint16_t **refcount_table, +- int64_t *nb_clusters) +-{ +- BDRVQcowState *s = bs->opaque; +- int64_t i; +- QCowSnapshot *sn; +- int ret; +- +- *refcount_table = g_try_new0(uint16_t, *nb_clusters); +- if (*nb_clusters && *refcount_table == NULL) { +- res->check_errors++; +- return -ENOMEM; +- } +- +- /* header */ +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- 0, s->cluster_size); +- +- /* current L1 table */ +- ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, +- s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); +- if (ret < 0) { +- return ret; +- } +- +- /* snapshots */ +- for (i = 0; i < s->nb_snapshots; i++) { +- sn = s->snapshots + i; +- ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, +- sn->l1_table_offset, sn->l1_size, 0); +- if (ret < 0) { +- return ret; +- } +- } +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- s->snapshots_offset, s->snapshots_size); +- +- /* refcount data */ +- inc_refcounts(bs, res, *refcount_table, *nb_clusters, +- s->refcount_table_offset, +- s->refcount_table_size * sizeof(uint64_t)); +- +- return check_refblocks(bs, res, fix, refcount_table, nb_clusters); +-} +- + /* + * Checks consistency of refblocks and accounts for each refblock in + * *refcount_table. +@@ -1631,6 +1578,55 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* ++ * Calculates an in-memory refcount table. ++ */ ++static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix, uint16_t **refcount_table, ++ int64_t *nb_clusters) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t i; ++ QCowSnapshot *sn; ++ int ret; ++ ++ *refcount_table = g_try_new0(uint16_t, *nb_clusters); ++ if (*nb_clusters && *refcount_table == NULL) { ++ res->check_errors++; ++ return -ENOMEM; ++ } ++ ++ /* header */ ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ 0, s->cluster_size); ++ ++ /* current L1 table */ ++ ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, ++ s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ /* snapshots */ ++ for (i = 0; i < s->nb_snapshots; i++) { ++ sn = s->snapshots + i; ++ ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, ++ sn->l1_table_offset, sn->l1_size, 0); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ s->snapshots_offset, s->snapshots_size); ++ ++ /* refcount data */ ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, ++ s->refcount_table_offset, ++ s->refcount_table_size * sizeof(uint64_t)); ++ ++ return check_refblocks(bs, res, fix, refcount_table, nb_clusters); ++} ++ ++/* + * Compares the actual reference count for each cluster in the image against the + * refcount as reported by the refcount structures on-disk. + */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Put-cache-reference-in-error-case.patch b/SOURCES/kvm-qcow2-Put-cache-reference-in-error-case.patch new file mode 100644 index 0000000..3362fe9 --- /dev/null +++ b/SOURCES/kvm-qcow2-Put-cache-reference-in-error-case.patch @@ -0,0 +1,46 @@ +From 9c887fdb82a6500aec6897f5c7f48f6bd31a33fc Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:21:55 +0200 +Subject: [PATCH 01/42] qcow2: Put cache reference in error case + +Message-id: <1434212556-3927-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 66020 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 01/42] qcow2: Put cache reference in error case +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +When qcow2_get_cluster_offset() sees a zero cluster in a version 2 +image, it (rightfully) returns an error. But in doing so it shouldn't +leak an L2 table cache reference. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +(cherry picked from commit 8885eadedd0ea8b57c1baa367ee2c2d616700bd9) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 81d90d9..1b9609f 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -481,6 +481,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, + break; + case QCOW2_CLUSTER_ZERO: + if (s->qcow_version < 3) { ++ qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + return -EIO; + } + c = count_contiguous_clusters(nb_clusters, s->cluster_size, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Rebuild-refcount-structure-during-check.patch b/SOURCES/kvm-qcow2-Rebuild-refcount-structure-during-check.patch new file mode 100644 index 0000000..4fd3f2d --- /dev/null +++ b/SOURCES/kvm-qcow2-Rebuild-refcount-structure-during-check.patch @@ -0,0 +1,374 @@ +From 3be020259d1627f335fe27aac1dc55e1249b7390 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:22 +0200 +Subject: [PATCH 28/42] qcow2: Rebuild refcount structure during check + +Message-id: <1434212556-3927-29-git-send-email-mreitz@redhat.com> +Patchwork-id: 66047 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 28/42] qcow2: Rebuild refcount structure during check +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +The previous commit introduced the "rebuild" variable to qcow2's +implementation of the image consistency check. Now make use of this by +adding a function which creates a completely new refcount structure +based solely on the in-memory information gathered before. + +The old refcount structure will be leaked, however. This leak will be +dealt with in a follow-up commit. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit c7c0681bc8a781e0319b7cf969b904dfe50d083e) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 305 insertions(+), 6 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 3d66e7c..651ddb6 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1660,6 +1660,285 @@ static void compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* ++ * Allocates clusters using an in-memory refcount table (IMRT) in contrast to ++ * the on-disk refcount structures. ++ * ++ * On input, *first_free_cluster tells where to start looking, and need not ++ * actually be a free cluster; the returned offset will not be before that ++ * cluster. On output, *first_free_cluster points to the first gap found, even ++ * if that gap was too small to be used as the returned offset. ++ * ++ * Note that *first_free_cluster is a cluster index whereas the return value is ++ * an offset. ++ */ ++static int64_t alloc_clusters_imrt(BlockDriverState *bs, ++ int cluster_count, ++ uint16_t **refcount_table, ++ int64_t *imrt_nb_clusters, ++ int64_t *first_free_cluster) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t cluster = *first_free_cluster, i; ++ bool first_gap = true; ++ int contiguous_free_clusters; ++ ++ /* Starting at *first_free_cluster, find a range of at least cluster_count ++ * continuously free clusters */ ++ for (contiguous_free_clusters = 0; ++ cluster < *imrt_nb_clusters && ++ contiguous_free_clusters < cluster_count; ++ cluster++) ++ { ++ if (!(*refcount_table)[cluster]) { ++ contiguous_free_clusters++; ++ if (first_gap) { ++ /* If this is the first free cluster found, update ++ * *first_free_cluster accordingly */ ++ *first_free_cluster = cluster; ++ first_gap = false; ++ } ++ } else if (contiguous_free_clusters) { ++ contiguous_free_clusters = 0; ++ } ++ } ++ ++ /* If contiguous_free_clusters is greater than zero, it contains the number ++ * of continuously free clusters until the current cluster; the first free ++ * cluster in the current "gap" is therefore ++ * cluster - contiguous_free_clusters */ ++ ++ /* If no such range could be found, grow the in-memory refcount table ++ * accordingly to append free clusters at the end of the image */ ++ if (contiguous_free_clusters < cluster_count) { ++ int64_t old_imrt_nb_clusters = *imrt_nb_clusters; ++ uint16_t *new_refcount_table; ++ ++ /* contiguous_free_clusters clusters are already empty at the image end; ++ * we need cluster_count clusters; therefore, we have to allocate ++ * cluster_count - contiguous_free_clusters new clusters at the end of ++ * the image (which is the current value of cluster; note that cluster ++ * may exceed old_imrt_nb_clusters if *first_free_cluster pointed beyond ++ * the image end) */ ++ *imrt_nb_clusters = cluster + cluster_count - contiguous_free_clusters; ++ new_refcount_table = g_try_realloc(*refcount_table, ++ *imrt_nb_clusters * ++ sizeof(**refcount_table)); ++ if (!new_refcount_table) { ++ *imrt_nb_clusters = old_imrt_nb_clusters; ++ return -ENOMEM; ++ } ++ *refcount_table = new_refcount_table; ++ ++ memset(*refcount_table + old_imrt_nb_clusters, 0, ++ (*imrt_nb_clusters - old_imrt_nb_clusters) * ++ sizeof(**refcount_table)); ++ } ++ ++ /* Go back to the first free cluster */ ++ cluster -= contiguous_free_clusters; ++ for (i = 0; i < cluster_count; i++) { ++ (*refcount_table)[cluster + i] = 1; ++ } ++ ++ return cluster << s->cluster_bits; ++} ++ ++/* ++ * Creates a new refcount structure based solely on the in-memory information ++ * given through *refcount_table. All necessary allocations will be reflected ++ * in that array. ++ * ++ * On success, the old refcount structure is leaked (it will be covered by the ++ * new refcount structure). ++ */ ++static int rebuild_refcount_structure(BlockDriverState *bs, ++ BdrvCheckResult *res, ++ uint16_t **refcount_table, ++ int64_t *nb_clusters) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t first_free_cluster = 0, reftable_offset = -1, cluster = 0; ++ int64_t refblock_offset, refblock_start, refblock_index; ++ uint32_t reftable_size = 0; ++ uint64_t *on_disk_reftable = NULL; ++ uint16_t *on_disk_refblock; ++ int i, ret = 0; ++ struct { ++ uint64_t reftable_offset; ++ uint32_t reftable_clusters; ++ } QEMU_PACKED reftable_offset_and_clusters; ++ ++ qcow2_cache_empty(bs, s->refcount_block_cache); ++ ++write_refblocks: ++ for (; cluster < *nb_clusters; cluster++) { ++ if (!(*refcount_table)[cluster]) { ++ continue; ++ } ++ ++ refblock_index = cluster >> s->refcount_block_bits; ++ refblock_start = refblock_index << s->refcount_block_bits; ++ ++ /* Don't allocate a cluster in a refblock already written to disk */ ++ if (first_free_cluster < refblock_start) { ++ first_free_cluster = refblock_start; ++ } ++ refblock_offset = alloc_clusters_imrt(bs, 1, refcount_table, ++ nb_clusters, &first_free_cluster); ++ if (refblock_offset < 0) { ++ fprintf(stderr, "ERROR allocating refblock: %s\n", ++ strerror(-refblock_offset)); ++ res->check_errors++; ++ ret = refblock_offset; ++ goto fail; ++ } ++ ++ if (reftable_size <= refblock_index) { ++ uint32_t old_reftable_size = reftable_size; ++ uint64_t *new_on_disk_reftable; ++ ++ reftable_size = ROUND_UP((refblock_index + 1) * sizeof(uint64_t), ++ s->cluster_size) / sizeof(uint64_t); ++ new_on_disk_reftable = g_try_realloc(on_disk_reftable, ++ reftable_size * ++ sizeof(uint64_t)); ++ if (!new_on_disk_reftable) { ++ res->check_errors++; ++ ret = -ENOMEM; ++ goto fail; ++ } ++ on_disk_reftable = new_on_disk_reftable; ++ ++ memset(on_disk_reftable + old_reftable_size, 0, ++ (reftable_size - old_reftable_size) * sizeof(uint64_t)); ++ ++ /* The offset we have for the reftable is now no longer valid; ++ * this will leak that range, but we can easily fix that by running ++ * a leak-fixing check after this rebuild operation */ ++ reftable_offset = -1; ++ } ++ on_disk_reftable[refblock_index] = refblock_offset; ++ ++ /* If this is apparently the last refblock (for now), try to squeeze the ++ * reftable in */ ++ if (refblock_index == (*nb_clusters - 1) >> s->refcount_block_bits && ++ reftable_offset < 0) ++ { ++ uint64_t reftable_clusters = size_to_clusters(s, reftable_size * ++ sizeof(uint64_t)); ++ reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, ++ refcount_table, nb_clusters, ++ &first_free_cluster); ++ if (reftable_offset < 0) { ++ fprintf(stderr, "ERROR allocating reftable: %s\n", ++ strerror(-reftable_offset)); ++ res->check_errors++; ++ ret = reftable_offset; ++ goto fail; ++ } ++ } ++ ++ ret = qcow2_pre_write_overlap_check(bs, 0, refblock_offset, ++ s->cluster_size); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); ++ goto fail; ++ } ++ ++ on_disk_refblock = qemu_blockalign0(bs->file, s->cluster_size); ++ for (i = 0; i < s->refcount_block_size && ++ refblock_start + i < *nb_clusters; i++) ++ { ++ on_disk_refblock[i] = ++ cpu_to_be16((*refcount_table)[refblock_start + i]); ++ } ++ ++ ret = bdrv_write(bs->file, refblock_offset / BDRV_SECTOR_SIZE, ++ (void *)on_disk_refblock, s->cluster_sectors); ++ qemu_vfree(on_disk_refblock); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR writing refblock: %s\n", strerror(-ret)); ++ goto fail; ++ } ++ ++ /* Go to the end of this refblock */ ++ cluster = refblock_start + s->refcount_block_size - 1; ++ } ++ ++ if (reftable_offset < 0) { ++ uint64_t post_refblock_start, reftable_clusters; ++ ++ post_refblock_start = ROUND_UP(*nb_clusters, s->refcount_block_size); ++ reftable_clusters = size_to_clusters(s, ++ reftable_size * sizeof(uint64_t)); ++ /* Not pretty but simple */ ++ if (first_free_cluster < post_refblock_start) { ++ first_free_cluster = post_refblock_start; ++ } ++ reftable_offset = alloc_clusters_imrt(bs, reftable_clusters, ++ refcount_table, nb_clusters, ++ &first_free_cluster); ++ if (reftable_offset < 0) { ++ fprintf(stderr, "ERROR allocating reftable: %s\n", ++ strerror(-reftable_offset)); ++ res->check_errors++; ++ ret = reftable_offset; ++ goto fail; ++ } ++ ++ goto write_refblocks; ++ } ++ ++ assert(on_disk_reftable); ++ ++ for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) { ++ cpu_to_be64s(&on_disk_reftable[refblock_index]); ++ } ++ ++ ret = qcow2_pre_write_overlap_check(bs, 0, reftable_offset, ++ reftable_size * sizeof(uint64_t)); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); ++ goto fail; ++ } ++ ++ assert(reftable_size < INT_MAX / sizeof(uint64_t)); ++ ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable, ++ reftable_size * sizeof(uint64_t)); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR writing reftable: %s\n", strerror(-ret)); ++ goto fail; ++ } ++ ++ /* Enter new reftable into the image header */ ++ cpu_to_be64w(&reftable_offset_and_clusters.reftable_offset, ++ reftable_offset); ++ cpu_to_be32w(&reftable_offset_and_clusters.reftable_clusters, ++ size_to_clusters(s, reftable_size * sizeof(uint64_t))); ++ ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, ++ refcount_table_offset), ++ &reftable_offset_and_clusters, ++ sizeof(reftable_offset_and_clusters)); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR setting reftable: %s\n", strerror(-ret)); ++ goto fail; ++ } ++ ++ for (refblock_index = 0; refblock_index < reftable_size; refblock_index++) { ++ be64_to_cpus(&on_disk_reftable[refblock_index]); ++ } ++ s->refcount_table = on_disk_reftable; ++ s->refcount_table_offset = reftable_offset; ++ s->refcount_table_size = reftable_size; ++ ++ return 0; ++ ++fail: ++ g_free(on_disk_reftable); ++ return ret; ++} ++ ++/* + * Checks an image for refcount consistency. + * + * Returns 0 if no errors are found, the number of errors in case the image is +@@ -1669,6 +1948,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix) + { + BDRVQcowState *s = bs->opaque; ++ BdrvCheckResult pre_compare_res; + int64_t size, highest_cluster, nb_clusters; + uint16_t *refcount_table = NULL; + bool rebuild = false; +@@ -1695,14 +1975,33 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + goto fail; + } + +- compare_refcounts(bs, res, fix, &rebuild, &highest_cluster, refcount_table, ++ /* In case we don't need to rebuild the refcount structure (but want to fix ++ * something), this function is immediately called again, in which case the ++ * result should be ignored */ ++ pre_compare_res = *res; ++ compare_refcounts(bs, res, 0, &rebuild, &highest_cluster, refcount_table, + nb_clusters); + +- if (rebuild) { +- fprintf(stderr, "ERROR need to rebuild refcount structures\n"); +- res->check_errors++; +- /* Just carry on, the rest does not rely on the on-disk refcount +- * structures */ ++ if (rebuild && (fix & BDRV_FIX_ERRORS)) { ++ fprintf(stderr, "Rebuilding refcount structure\n"); ++ ret = rebuild_refcount_structure(bs, res, &refcount_table, ++ &nb_clusters); ++ if (ret < 0) { ++ goto fail; ++ } ++ } else if (fix) { ++ if (rebuild) { ++ fprintf(stderr, "ERROR need to rebuild refcount structures\n"); ++ res->check_errors++; ++ ret = -EIO; ++ goto fail; ++ } ++ ++ if (res->leaks || res->corruptions) { ++ *res = pre_compare_res; ++ compare_refcounts(bs, res, fix, &rebuild, &highest_cluster, ++ refcount_table, nb_clusters); ++ } + } + + /* check OFLAG_COPIED */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Respect-new_block-in-alloc_refcount_block.patch b/SOURCES/kvm-qcow2-Respect-new_block-in-alloc_refcount_block.patch new file mode 100644 index 0000000..d29e781 --- /dev/null +++ b/SOURCES/kvm-qcow2-Respect-new_block-in-alloc_refcount_block.patch @@ -0,0 +1,72 @@ +From 9bffc974294d823d42b4b4d51e44abd26f7147a6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:33 +0200 +Subject: [PATCH 39/42] qcow2: Respect new_block in alloc_refcount_block() + +Message-id: <1434212556-3927-40-git-send-email-mreitz@redhat.com> +Patchwork-id: 66058 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 39/42] qcow2: Respect new_block in alloc_refcount_block() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +When choosing a new place for the refcount table, alloc_refcount_block() +tries to infer the number of clusters used so far from its argument +cluster_index (which comes from the idea that if any cluster with an +index greater than cluster_index was in use, the refcount table would +have to be big enough already to describe cluster_index). + +However, there is a cluster that may be at or after cluster_index, and +which is not covered by the refcount structures, and that is the new +refcount block new_block. Therefore, it should be taken into account for +the blocks_used calculation. + +Also, because new_block already describes (or is intended to describe) +cluster_index, we may not put the new refcount structures there. + +Signed-off-by: Max Reitz +Message-id: 1423598552-24301-2-git-send-email-mreitz@redhat.com +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Signed-off-by: Max Reitz +(cherry picked from commit 14a58a4e0c2e98a7d9232e1c229a531ca231133b) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 87b932c..cee5b1f 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -319,8 +319,20 @@ static int alloc_refcount_block(BlockDriverState *bs, + */ + BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW); + +- /* Calculate the number of refcount blocks needed so far */ +- uint64_t blocks_used = DIV_ROUND_UP(cluster_index, s->refcount_block_size); ++ /* Calculate the number of refcount blocks needed so far; this will be the ++ * basis for calculating the index of the first cluster used for the ++ * self-describing refcount structures which we are about to create. ++ * ++ * Because we reached this point, there cannot be any refcount entries for ++ * cluster_index or higher indices yet. However, because new_block has been ++ * allocated to describe that cluster (and it will assume this role later ++ * on), we cannot use that index; also, new_block may actually have a higher ++ * cluster index than cluster_index, so it needs to be taken into account ++ * here (and 1 needs to be added to its value because that cluster is used). ++ */ ++ uint64_t blocks_used = DIV_ROUND_UP(MAX(cluster_index + 1, ++ (new_block >> s->cluster_bits) + 1), ++ s->refcount_block_size); + + if (blocks_used > QCOW_MAX_REFTABLE_SIZE / sizeof(uint64_t)) { + return -EFBIG; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Reuse-refcount-table-in-calculate_refcounts.patch b/SOURCES/kvm-qcow2-Reuse-refcount-table-in-calculate_refcounts.patch new file mode 100644 index 0000000..184576a --- /dev/null +++ b/SOURCES/kvm-qcow2-Reuse-refcount-table-in-calculate_refcounts.patch @@ -0,0 +1,66 @@ +From 2f67e26a87ace81cb7a9c122c39f4d8d667d69d1 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:19 +0200 +Subject: [PATCH 25/42] qcow2: Reuse refcount table in calculate_refcounts() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-26-git-send-email-mreitz@redhat.com> +Patchwork-id: 66044 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 25/42] qcow2: Reuse refcount table in calculate_refcounts() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +We will later call calculate_refcounts multiple times, so reuse the +refcount table if possible. + +Signed-off-by: Max Reitz +Reviewed-by: Benoît Canet +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit 9696df219a71c6608f058ade8873d6d0b4e352fe) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 7d03e65..8f1215c 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1631,10 +1631,12 @@ static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + QCowSnapshot *sn; + int ret; + +- *refcount_table = g_try_new0(uint16_t, *nb_clusters); +- if (*nb_clusters && *refcount_table == NULL) { +- res->check_errors++; +- return -ENOMEM; ++ if (!*refcount_table) { ++ *refcount_table = g_try_new0(uint16_t, *nb_clusters); ++ if (*nb_clusters && *refcount_table == NULL) { ++ res->check_errors++; ++ return -ENOMEM; ++ } + } + + /* header */ +@@ -1750,7 +1752,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + { + BDRVQcowState *s = bs->opaque; + int64_t size, highest_cluster, nb_clusters; +- uint16_t *refcount_table; ++ uint16_t *refcount_table = NULL; + int ret; + + size = bdrv_getlength(bs->file); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Split-fail-code-in-L1-and-L2-checks.patch b/SOURCES/kvm-qcow2-Split-fail-code-in-L1-and-L2-checks.patch new file mode 100644 index 0000000..8767cdf --- /dev/null +++ b/SOURCES/kvm-qcow2-Split-fail-code-in-L1-and-L2-checks.patch @@ -0,0 +1,111 @@ +From f3113f5709ae7c1f1ca25b6075662c49fc415ca7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:16 +0200 +Subject: [PATCH 22/42] qcow2: Split fail code in L1 and L2 checks + +Message-id: <1434212556-3927-23-git-send-email-mreitz@redhat.com> +Patchwork-id: 66041 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 22/42] qcow2: Split fail code in L1 and L2 checks +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Instead of printing out an error message, incrementing check_errors and +returning a fixed -errno, just do cleanups and return -ret, with ret set +by the code which threw the exception (jumped to the fail label). + +Also, increment check_errors on error in check_refcounts_l2(). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit ad27390c85c50df402c7ec0d3864fc43e6559fb3) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2-refcount.c + +One conflict because of g_malloc() downstream instead of g_try_malloc() +(contextual); I fixed up the context because there was no real reason +not to. + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 7e2bb7d..0dac4c9 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1105,14 +1105,18 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, + BDRVQcowState *s = bs->opaque; + uint64_t *l2_table, l2_entry; + uint64_t next_contiguous_offset = 0; +- int i, l2_size, nb_csectors; ++ int i, l2_size, nb_csectors, ret; + + /* Read L2 table from disk */ + l2_size = s->l2_size * sizeof(uint64_t); + l2_table = g_malloc(l2_size); + +- if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size) ++ ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n"); ++ res->check_errors++; + goto fail; ++ } + + /* Do the actual checks */ + for(i = 0; i < s->l2_size; i++) { +@@ -1193,9 +1197,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, + return 0; + + fail: +- fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n"); + g_free(l2_table); +- return -EIO; ++ return ret; + } + + /* +@@ -1227,10 +1230,18 @@ static int check_refcounts_l1(BlockDriverState *bs, + if (l1_size2 == 0) { + l1_table = NULL; + } else { +- l1_table = g_malloc(l1_size2); +- if (bdrv_pread(bs->file, l1_table_offset, +- l1_table, l1_size2) != l1_size2) ++ l1_table = g_try_malloc(l1_size2); ++ if (l1_table == NULL) { ++ ret = -ENOMEM; ++ res->check_errors++; ++ goto fail; ++ } ++ ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n"); ++ res->check_errors++; + goto fail; ++ } + for(i = 0;i < l1_size; i++) + be64_to_cpus(&l1_table[i]); + } +@@ -1263,10 +1274,8 @@ static int check_refcounts_l1(BlockDriverState *bs, + return 0; + + fail: +- fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n"); +- res->check_errors++; + g_free(l1_table); +- return -EIO; ++ return ret; + } + + /* +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Split-qcow2_check_refcounts.patch b/SOURCES/kvm-qcow2-Split-qcow2_check_refcounts.patch new file mode 100644 index 0000000..c7b4bef --- /dev/null +++ b/SOURCES/kvm-qcow2-Split-qcow2_check_refcounts.patch @@ -0,0 +1,289 @@ +From 735513ff089e56379c2cfd290c5b3e1f1a13cbcc Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:12 +0200 +Subject: [PATCH 18/42] qcow2: Split qcow2_check_refcounts() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-19-git-send-email-mreitz@redhat.com> +Patchwork-id: 66037 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 18/42] qcow2: Split qcow2_check_refcounts() +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Put the code for calculating the reference counts and comparing them +during qemu-img check into own functions. + +Signed-off-by: Max Reitz +Reviewed-by: Benoît Canet +Reviewed-by: Kevin Wolf +Signed-off-by: Kevin Wolf +(cherry picked from commit 6ca56bf5e90aa167395727667d17c699950c545c) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2-refcount.c + +5839e53bbc0fec56021d758aab7610df421ed8c8 is missing downstream, which +replaces g*_malloc*() by g*_new*() and g*_realloc() by g*_renew() all +over the code base. Not backporting that commit results in only two +conflicts which are trivial to resolve; backporting it would mean +touching the whole code base, which I think is worse. + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 151 +++++++++++++++++++++++++++++++++---------------- + 1 file changed, 103 insertions(+), 48 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 0c5a6ad..08b2b62 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1501,67 +1501,70 @@ fail: + return new_offset; + } + ++static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix, uint16_t **refcount_table, ++ int64_t *nb_clusters); ++ + /* +- * Checks an image for refcount consistency. +- * +- * Returns 0 if no errors are found, the number of errors in case the image is +- * detected as corrupted, and -errno when an internal error occurred. ++ * Calculates an in-memory refcount table. + */ +-int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, +- BdrvCheckMode fix) ++static int calculate_refcounts(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix, uint16_t **refcount_table, ++ int64_t *nb_clusters) + { + BDRVQcowState *s = bs->opaque; +- int64_t size, i, highest_cluster, nb_clusters; +- int refcount1, refcount2; ++ int64_t i; + QCowSnapshot *sn; +- uint16_t *refcount_table; + int ret; + +- size = bdrv_getlength(bs->file); +- if (size < 0) { ++ *refcount_table = g_try_new0(uint16_t, *nb_clusters); ++ if (*nb_clusters && *refcount_table == NULL) { + res->check_errors++; +- return size; ++ return -ENOMEM; + } + +- nb_clusters = size_to_clusters(s, size); +- if (nb_clusters > INT_MAX) { +- res->check_errors++; +- return -EFBIG; +- } +- +- refcount_table = g_malloc0(nb_clusters * sizeof(uint16_t)); +- +- res->bfi.total_clusters = +- size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE); +- + /* header */ +- inc_refcounts(bs, res, refcount_table, nb_clusters, ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, + 0, s->cluster_size); + + /* current L1 table */ +- ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, ++ ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, + s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); + if (ret < 0) { +- goto fail; ++ return ret; + } + + /* snapshots */ +- for(i = 0; i < s->nb_snapshots; i++) { ++ for (i = 0; i < s->nb_snapshots; i++) { + sn = s->snapshots + i; +- ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, ++ ret = check_refcounts_l1(bs, res, *refcount_table, *nb_clusters, + sn->l1_table_offset, sn->l1_size, 0); + if (ret < 0) { +- goto fail; ++ return ret; + } + } +- inc_refcounts(bs, res, refcount_table, nb_clusters, ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, + s->snapshots_offset, s->snapshots_size); + + /* refcount data */ +- inc_refcounts(bs, res, refcount_table, nb_clusters, ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, + s->refcount_table_offset, + s->refcount_table_size * sizeof(uint64_t)); + ++ return check_refblocks(bs, res, fix, refcount_table, nb_clusters); ++} ++ ++/* ++ * Checks consistency of refblocks and accounts for each refblock in ++ * *refcount_table. ++ */ ++static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix, uint16_t **refcount_table, ++ int64_t *nb_clusters) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t i; ++ + for(i = 0; i < s->refcount_table_size; i++) { + uint64_t offset, cluster; + offset = s->refcount_table[i]; +@@ -1575,7 +1578,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + continue; + } + +- if (cluster >= nb_clusters) { ++ if (cluster >= *nb_clusters) { + fprintf(stderr, "ERROR refcount block %" PRId64 + " is outside image\n", i); + res->corruptions++; +@@ -1583,14 +1586,14 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + if (offset != 0) { +- inc_refcounts(bs, res, refcount_table, nb_clusters, ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, + offset, s->cluster_size); +- if (refcount_table[cluster] != 1) { ++ if ((*refcount_table)[cluster] != 1) { + fprintf(stderr, "%s refcount block %" PRId64 + " refcount=%d\n", + fix & BDRV_FIX_ERRORS ? "Repairing" : + "ERROR", +- i, refcount_table[cluster]); ++ i, (*refcount_table)[cluster]); + + if (fix & BDRV_FIX_ERRORS) { + int64_t new_offset; +@@ -1602,17 +1605,18 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* update refcounts */ +- if ((new_offset >> s->cluster_bits) >= nb_clusters) { ++ if ((new_offset >> s->cluster_bits) >= *nb_clusters) { + /* increase refcount_table size if necessary */ +- int old_nb_clusters = nb_clusters; +- nb_clusters = (new_offset >> s->cluster_bits) + 1; +- refcount_table = g_realloc(refcount_table, +- nb_clusters * sizeof(uint16_t)); +- memset(&refcount_table[old_nb_clusters], 0, (nb_clusters +- - old_nb_clusters) * sizeof(uint16_t)); ++ int old_nb_clusters = *nb_clusters; ++ *nb_clusters = (new_offset >> s->cluster_bits) + 1; ++ *refcount_table = g_renew(uint16_t, *refcount_table, ++ *nb_clusters); ++ memset(&(*refcount_table)[old_nb_clusters], 0, ++ (*nb_clusters - old_nb_clusters) * ++ sizeof(uint16_t)); + } +- refcount_table[cluster]--; +- inc_refcounts(bs, res, refcount_table, nb_clusters, ++ (*refcount_table)[cluster]--; ++ inc_refcounts(bs, res, *refcount_table, *nb_clusters, + new_offset, s->cluster_size); + + res->corruptions_fixed++; +@@ -1623,8 +1627,22 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + } + +- /* compare ref counts */ +- for (i = 0, highest_cluster = 0; i < nb_clusters; i++) { ++ return 0; ++} ++ ++/* ++ * Compares the actual reference count for each cluster in the image against the ++ * refcount as reported by the refcount structures on-disk. ++ */ ++static void compare_refcounts(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix, int64_t *highest_cluster, ++ uint16_t *refcount_table, int64_t nb_clusters) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t i; ++ int refcount1, refcount2, ret; ++ ++ for (i = 0, *highest_cluster = 0; i < nb_clusters; i++) { + refcount1 = get_refcount(bs, i); + if (refcount1 < 0) { + fprintf(stderr, "Can't get refcount for cluster %" PRId64 ": %s\n", +@@ -1636,11 +1654,10 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + refcount2 = refcount_table[i]; + + if (refcount1 > 0 || refcount2 > 0) { +- highest_cluster = i; ++ *highest_cluster = i; + } + + if (refcount1 != refcount2) { +- + /* Check if we're allowed to fix the mismatch */ + int *num_fixed = NULL; + if (refcount1 > refcount2 && (fix & BDRV_FIX_LEAKS)) { +@@ -1673,6 +1690,44 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + } + } ++} ++ ++/* ++ * Checks an image for refcount consistency. ++ * ++ * Returns 0 if no errors are found, the number of errors in case the image is ++ * detected as corrupted, and -errno when an internal error occurred. ++ */ ++int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int64_t size, highest_cluster, nb_clusters; ++ uint16_t *refcount_table; ++ int ret; ++ ++ size = bdrv_getlength(bs->file); ++ if (size < 0) { ++ res->check_errors++; ++ return size; ++ } ++ ++ nb_clusters = size_to_clusters(s, size); ++ if (nb_clusters > INT_MAX) { ++ res->check_errors++; ++ return -EFBIG; ++ } ++ ++ res->bfi.total_clusters = ++ size_to_clusters(s, bs->total_sectors * BDRV_SECTOR_SIZE); ++ ++ ret = calculate_refcounts(bs, res, fix, &refcount_table, &nb_clusters); ++ if (ret < 0) { ++ goto fail; ++ } ++ ++ compare_refcounts(bs, res, fix, &highest_cluster, refcount_table, ++ nb_clusters); + + /* check OFLAG_COPIED */ + ret = check_oflag_copied(bs, res, fix); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Use-int64_t-for-in-memory-reftable-size.patch b/SOURCES/kvm-qcow2-Use-int64_t-for-in-memory-reftable-size.patch new file mode 100644 index 0000000..8a70b61 --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-int64_t-for-in-memory-reftable-size.patch @@ -0,0 +1,62 @@ +From 47b574df6debd01336650992a1faed4bfeec4814 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:15 +0200 +Subject: [PATCH 21/42] qcow2: Use int64_t for in-memory reftable size + +Message-id: <1434212556-3927-22-git-send-email-mreitz@redhat.com> +Patchwork-id: 66040 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 21/42] qcow2: Use int64_t for in-memory reftable size +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Use int64_t for the entry count of the in-memory refcount table +throughout the check functions. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 713d9675e0e31c627d08b6a33d3a92e4b8505b40) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 0d10865..7e2bb7d 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1056,7 +1056,7 @@ fail: + static void inc_refcounts(BlockDriverState *bs, + BdrvCheckResult *res, + uint16_t *refcount_table, +- int refcount_table_size, ++ int64_t refcount_table_size, + int64_t offset, int64_t size) + { + BDRVQcowState *s = bs->opaque; +@@ -1099,7 +1099,7 @@ enum { + * error occurred. + */ + static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, +- uint16_t *refcount_table, int refcount_table_size, int64_t l2_offset, ++ uint16_t *refcount_table, int64_t refcount_table_size, int64_t l2_offset, + int flags) + { + BDRVQcowState *s = bs->opaque; +@@ -1209,7 +1209,7 @@ fail: + static int check_refcounts_l1(BlockDriverState *bs, + BdrvCheckResult *res, + uint16_t *refcount_table, +- int refcount_table_size, ++ int64_t refcount_table_size, + int64_t l1_table_offset, int l1_size, + int flags) + { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Use-qcow2_signal_corruption-for-overlaps.patch b/SOURCES/kvm-qcow2-Use-qcow2_signal_corruption-for-overlaps.patch new file mode 100644 index 0000000..eb56630 --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-qcow2_signal_corruption-for-overlaps.patch @@ -0,0 +1,135 @@ +From e7eca18cb5fec2c7c99b8e0335d630cc368f712b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:03 +0200 +Subject: [PATCH 09/42] qcow2: Use qcow2_signal_corruption() for overlaps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1434212556-3927-10-git-send-email-mreitz@redhat.com> +Patchwork-id: 66028 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 09/42] qcow2: Use qcow2_signal_corruption() for overlaps +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +Use the new function in case of a failed overlap check. + +This changes output in case of corruption, so adapt iotest 060's +reference output accordingly. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Benoît Canet +Message-id: 1409926039-29044-4-git-send-email-mreitz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit adb435522b86b3fca2324cb8c94e17b55ae071f1) +Signed-off-by: Miroslav Rezanina + +Conflicts: + block/qcow2-refcount.c + +qcow2_pre_write_overlap_check() did not use qapi_event_send_*() +downstream, but that code is being removed anyway. + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 21 +++------------------ + tests/qemu-iotests/060.out | 10 +++++----- + 2 files changed, 8 insertions(+), 23 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 6fa6daf..dbcc4c6 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -26,7 +26,6 @@ + #include "block/block_int.h" + #include "block/qcow2.h" + #include "qemu/range.h" +-#include "qapi/qmp/types.h" + + static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size); + static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, +@@ -1795,25 +1794,11 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, + return ret; + } else if (ret > 0) { + int metadata_ol_bitnr = ffs(ret) - 1; +- char *message; +- QObject *data; +- + assert(metadata_ol_bitnr < QCOW2_OL_MAX_BITNR); + +- fprintf(stderr, "qcow2: Preventing invalid write on metadata (overlaps " +- "with %s); image marked as corrupt.\n", +- metadata_ol_names[metadata_ol_bitnr]); +- message = g_strdup_printf("Prevented %s overwrite", +- metadata_ol_names[metadata_ol_bitnr]); +- data = qobject_from_jsonf("{ 'device': %s, 'msg': %s, 'offset': %" +- PRId64 ", 'size': %" PRId64 ", 'fatal': true }", +- bs->device_name, message, offset, size); +- monitor_protocol_event(QEVENT_BLOCK_IMAGE_CORRUPTED, data); +- g_free(message); +- qobject_decref(data); +- +- qcow2_mark_corrupt(bs); +- bs->drv = NULL; /* make BDS unusable */ ++ qcow2_signal_corruption(bs, true, offset, size, "Preventing invalid " ++ "write on metadata (overlaps with %s)", ++ metadata_ol_names[metadata_ol_bitnr]); + return -EIO; + } + +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +index c27c952..30806da 100644 +--- a/tests/qemu-iotests/060.out ++++ b/tests/qemu-iotests/060.out +@@ -8,7 +8,7 @@ ERROR cluster 3 refcount=1 reference=3 + 1 errors were found on the image. + Data may be corrupted, or further writes to the image may corrupt it. + incompatible_features 0x0 +-qcow2: Preventing invalid write on metadata (overlaps with active L1 table); image marked as corrupt. ++qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L1 table); further corruption events will be suppressed + write failed: Input/output error + incompatible_features 0x2 + qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write +@@ -24,7 +24,7 @@ ERROR cluster 2 refcount=1 reference=2 + 2 errors were found on the image. + Data may be corrupted, or further writes to the image may corrupt it. + incompatible_features 0x0 +-qcow2: Preventing invalid write on metadata (overlaps with refcount block); image marked as corrupt. ++qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with refcount block); further corruption events will be suppressed + write failed: Input/output error + incompatible_features 0x2 + Repairing refcount block 0 refcount=2 +@@ -56,7 +56,7 @@ Data may be corrupted, or further writes to the image may corrupt it. + 1 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + incompatible_features 0x0 +-qcow2: Preventing invalid write on metadata (overlaps with inactive L2 table); image marked as corrupt. ++qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with inactive L2 table); further corruption events will be suppressed + write failed: Input/output error + incompatible_features 0x2 + Repairing cluster 4 refcount=1 reference=2 +@@ -88,7 +88,7 @@ wrote 65536/65536 bytes at offset 536870912 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + discard 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qcow2: Preventing invalid write on metadata (overlaps with active L2 table); image marked as corrupt. ++qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with active L2 table); further corruption events will be suppressed + blkdebug: Suspended request '0' + write failed: Input/output error + blkdebug: Resuming request '0' +@@ -99,6 +99,6 @@ aio_write failed: No medium found + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + wrote 65536/65536 bytes at offset 0 + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-qcow2: Preventing invalid write on metadata (overlaps with qcow2_header); image marked as corrupt. ++qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed + write failed: Input/output error + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-Use-sizeof-refcount_table.patch b/SOURCES/kvm-qcow2-Use-sizeof-refcount_table.patch new file mode 100644 index 0000000..e976f43 --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-sizeof-refcount_table.patch @@ -0,0 +1,47 @@ +From be34caa9498a41766cdedf43613edf2e9600d896 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:13 +0200 +Subject: [PATCH 19/42] qcow2: Use sizeof(**refcount_table) + +Message-id: <1434212556-3927-20-git-send-email-mreitz@redhat.com> +Patchwork-id: 66038 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 19/42] qcow2: Use sizeof(**refcount_table) +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1129893 + +When implementing variable refcounts, we want to be able to easily find +all the places in qemu which are tied to a certain refcount order. +Replace sizeof(uint16_t) in the check code by sizeof(**refcount_table) +so we can later find it more easily. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 78fb328e854542d79bebe54f3a426cba6d46dbf1) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 08b2b62..cb78f05 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1613,7 +1613,7 @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res, + *nb_clusters); + memset(&(*refcount_table)[old_nb_clusters], 0, + (*nb_clusters - old_nb_clusters) * +- sizeof(uint16_t)); ++ sizeof(**refcount_table)); + } + (*refcount_table)[cluster]--; + inc_refcounts(bs, res, *refcount_table, *nb_clusters, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2-fix-leak-of-Qcow2DiscardRegion-in-update_refco.patch b/SOURCES/kvm-qcow2-fix-leak-of-Qcow2DiscardRegion-in-update_refco.patch new file mode 100644 index 0000000..d19fa33 --- /dev/null +++ b/SOURCES/kvm-qcow2-fix-leak-of-Qcow2DiscardRegion-in-update_refco.patch @@ -0,0 +1,47 @@ +From b0f23a00b51a43aefe975fd2748c9b079a499d95 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:06 +0200 +Subject: [PATCH 12/42] qcow2: fix leak of Qcow2DiscardRegion in + update_refcount_discard + +Message-id: <1434212556-3927-13-git-send-email-mreitz@redhat.com> +Patchwork-id: 66031 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 12/42] qcow2: fix leak of Qcow2DiscardRegion in update_refcount_discard +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Zhang Haoyu + +BZ: 1129893 + +When the Qcow2DiscardRegion is adjacent to another one referenced by "d", +free this Qcow2DiscardRegion metadata referenced by "p" after +it was removed from s->discards queue. + +Signed-off-by: Zhang Haoyu +Signed-off-by: Kevin Wolf +(cherry picked from commit d8bb71b6227366c188595b91c24a58c9b06e46dd) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index e66d593..0c5a6ad 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -509,6 +509,7 @@ found: + QTAILQ_REMOVE(&s->discards, p, next); + d->offset = MIN(d->offset, p->offset); + d->bytes += p->bytes; ++ g_free(p); + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qcow2.py-Add-required-padding-for-header-extensions.patch b/SOURCES/kvm-qcow2.py-Add-required-padding-for-header-extensions.patch new file mode 100644 index 0000000..cf5bb81 --- /dev/null +++ b/SOURCES/kvm-qcow2.py-Add-required-padding-for-header-extensions.patch @@ -0,0 +1,51 @@ +From 340c0aaeb771bc3c4b2347e4bcace7afe846907f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Sat, 13 Jun 2015 16:22:29 +0200 +Subject: [PATCH 35/42] qcow2.py: Add required padding for header extensions + +Message-id: <1434212556-3927-36-git-send-email-mreitz@redhat.com> +Patchwork-id: 66054 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 35/42] qcow2.py: Add required padding for header extensions +Bugzilla: 1129893 +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +BZ: 1129893 + +The qcow2 specification requires that the header extension data be +padded to round up the extension size to the next multiple of 8 bytes. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Message-id: 1416935562-7760-3-git-send-email-kwolf@redhat.com +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 8884dd1bbc5ce42cd657ffcbef3a477443468974) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/qcow2.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py +index 44a2b45..0e343ef 100755 +--- a/tests/qemu-iotests/qcow2.py ++++ b/tests/qemu-iotests/qcow2.py +@@ -7,6 +7,10 @@ import string + class QcowHeaderExtension: + + def __init__(self, magic, length, data): ++ if length % 8 != 0: ++ padding = 8 - (length % 8) ++ data += "\0" * padding ++ + self.magic = magic + self.length = length + self.data = data +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qdict-Add-qdict_join.patch b/SOURCES/kvm-qdict-Add-qdict_join.patch new file mode 100644 index 0000000..a81df96 --- /dev/null +++ b/SOURCES/kvm-qdict-Add-qdict_join.patch @@ -0,0 +1,89 @@ +From 08ab287975f409e420863a8d39e3b3add8ca6088 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Tue, 2 Jun 2015 09:46:36 +0200 +Subject: [PATCH 2/4] qdict: Add qdict_join() + +Message-id: <1433238397-2500-2-git-send-email-rjones@redhat.com> +Patchwork-id: 65278 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] qdict: Add qdict_join() +Bugzilla: 1226697 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +From: Max Reitz + +This function joins two QDicts by absorbing one into the other. + +Signed-off-by: Max Reitz +Reviewed-by: Benoit Canet +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + include/qapi/qmp/qdict.h | 3 +++ + qobject/qdict.c | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+) + +diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h +index d6855d1..fc6e2f2 100644 +--- a/include/qapi/qmp/qdict.h ++++ b/include/qapi/qmp/qdict.h +@@ -16,6 +16,7 @@ + #include "qapi/qmp/qobject.h" + #include "qapi/qmp/qlist.h" + #include "qemu/queue.h" ++#include + #include + + #define QDICT_BUCKET_MAX 512 +@@ -67,4 +68,6 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key); + QDict *qdict_clone_shallow(const QDict *src); + void qdict_flatten(QDict *qdict); + ++void qdict_join(QDict *dest, QDict *src, bool overwrite); ++ + #endif /* QDICT_H */ +diff --git a/qobject/qdict.c b/qobject/qdict.c +index 472f106..c7e35ae 100644 +--- a/qobject/qdict.c ++++ b/qobject/qdict.c +@@ -527,3 +527,35 @@ void qdict_flatten(QDict *qdict) + { + qdict_do_flatten(qdict, qdict, NULL); + } ++ ++/** ++ * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all ++ * elements from src to dest. ++ * ++ * If an element from src has a key already present in dest, it will not be ++ * moved unless overwrite is true. ++ * ++ * If overwrite is true, the conflicting values in dest will be discarded and ++ * replaced by the corresponding values from src. ++ * ++ * Therefore, with overwrite being true, the src QDict will always be empty when ++ * this function returns. If overwrite is false, the src QDict will be empty ++ * iff there were no conflicts. ++ */ ++void qdict_join(QDict *dest, QDict *src, bool overwrite) ++{ ++ const QDictEntry *entry, *next; ++ ++ entry = qdict_first(src); ++ while (entry) { ++ next = qdict_next(src, entry); ++ ++ if (overwrite || !qdict_haskey(dest, entry->key)) { ++ qobject_incref(entry->value); ++ qdict_put_obj(dest, entry->key, entry->value); ++ qdict_del(src, entry->key); ++ } ++ ++ entry = next; ++ } ++} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch b/SOURCES/kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch new file mode 100644 index 0000000..943bc6e --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch @@ -0,0 +1,41 @@ +From 8d7ac23276f1e17163a1679c2bf9b5bee09739a7 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 18 Sep 2015 11:08:50 +0200 +Subject: [PATCH] qemu-iotests: Filter qemu-io output in 025 + +Message-id: <1442574530-9690-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 67829 +O-Subject: [RHEL-7.2 qemu-kvm PATCH] qemu-iotests: Filter qemu-io output in 025 +Bugzilla: 1170974 +RH-Acked-by: John Snow +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz + +From: Fam Zheng + +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 0d83c98bf15269e80e3558dc2c7b27e2f4386158) +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/025 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/qemu-iotests/025 b/tests/qemu-iotests/025 +index a7241cc..9426c93 100755 +--- a/tests/qemu-iotests/025 ++++ b/tests/qemu-iotests/025 +@@ -56,7 +56,7 @@ _check_test_img + + echo + echo "=== Resizing image" +-$QEMU_IO "$TEST_IMG" < +Date: Mon, 25 May 2015 04:45:55 +0200 +Subject: [PATCH 3/6] qemu-iotests: Test unaligned 4k zero write + +Message-id: <1432529157-20381-2-git-send-email-famz@redhat.com> +Patchwork-id: 65119 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2 1/3] qemu-iotests: Test unaligned 4k zero write +Bugzilla: 1200295 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi + +Signed-off-by: Fam Zheng +Message-id: 1427160230-4489-3-git-send-email-famz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 61815d6e0aa1a549ad55f6621b6816aa6b1ab757) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/033 | 47 +++++++++++++++++++++++++++++----------------- + tests/qemu-iotests/033.out | 26 +++++++++++++++++++++++++ + 2 files changed, 56 insertions(+), 17 deletions(-) + +diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033 +index ea3351c..4008f10 100755 +--- a/tests/qemu-iotests/033 ++++ b/tests/qemu-iotests/033 +@@ -46,26 +46,39 @@ _supported_os Linux + size=128M + _make_test_img $size + +-echo +-echo "== preparing image ==" +-$QEMU_IO -c "write -P 0xa 0x200 0x400" "$TEST_IMG" | _filter_qemu_io +-$QEMU_IO -c "write -P 0xa 0x20000 0x600" "$TEST_IMG" | _filter_qemu_io +-$QEMU_IO -c "write -z 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io ++do_test() ++{ ++ local align=$1 ++ local iocmd=$2 ++ local img=$3 ++ { ++ echo "open -o driver=$IMGFMT,file.align=$align blkdebug::$img" ++ echo $iocmd ++ } | $QEMU_IO ++} ++ ++for align in 512 4k; do ++ echo ++ echo "== preparing image ==" ++ do_test $align "write -P 0xa 0x200 0x400" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "write -P 0xa 0x20000 0x600" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "write -z 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io + +-echo +-echo "== verifying patterns (1) ==" +-$QEMU_IO -c "read -P 0xa 0x200 0x200" "$TEST_IMG" | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io +-$QEMU_IO -c "read -P 0xa 0x20400 0x200" "$TEST_IMG" | _filter_qemu_io ++ echo ++ echo "== verifying patterns (1) ==" ++ do_test $align "read -P 0xa 0x200 0x200" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "read -P 0xa 0x20400 0x200" "$TEST_IMG" | _filter_qemu_io + +-echo +-echo "== rewriting zeroes ==" +-$QEMU_IO -c "write -P 0xb 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io +-$QEMU_IO -c "write -z 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io ++ echo ++ echo "== rewriting zeroes ==" ++ do_test $align "write -P 0xb 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "write -z 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io + +-echo +-echo "== verifying patterns (2) ==" +-$QEMU_IO -c "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io ++ echo ++ echo "== verifying patterns (2) ==" ++ do_test $align "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io ++done + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/033.out b/tests/qemu-iotests/033.out +index 2fe74df..344065f 100644 +--- a/tests/qemu-iotests/033.out ++++ b/tests/qemu-iotests/033.out +@@ -26,4 +26,30 @@ wrote 65536/65536 bytes at offset 65536 + == verifying patterns (2) == + read 131072/131072 bytes at offset 1024 + 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== preparing image == ++wrote 1024/1024 bytes at offset 512 ++1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 1536/1536 bytes at offset 131072 ++1.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 131072/131072 bytes at offset 1024 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== verifying patterns (1) == ++read 512/512 bytes at offset 512 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 131072/131072 bytes at offset 1024 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++read 512/512 bytes at offset 132096 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rewriting zeroes == ++wrote 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 65536/65536 bytes at offset 65536 ++64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== verifying patterns (2) == ++read 131072/131072 bytes at offset 1024 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Test-unaligned-sub-block-zero-write.patch b/SOURCES/kvm-qemu-iotests-Test-unaligned-sub-block-zero-write.patch new file mode 100644 index 0000000..3995465 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Test-unaligned-sub-block-zero-write.patch @@ -0,0 +1,101 @@ +From daca4d834e727c73565aa0659da6fab52ab7cc6b Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 25 May 2015 04:45:57 +0200 +Subject: [PATCH 5/6] qemu-iotests: Test unaligned sub-block zero write + +Message-id: <1432529157-20381-4-git-send-email-famz@redhat.com> +Patchwork-id: 65121 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2 3/3] qemu-iotests: Test unaligned sub-block zero write +Bugzilla: 1200295 +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi + +Test zero write in byte range 512~1024 for 4k alignment. + +Signed-off-by: Fam Zheng +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Kevin Wolf +Message-id: 1431522721-3266-4-git-send-email-famz@redhat.com +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit ab53c44718305d3fde3d9d2251889f1cab694be2) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/033 | 13 +++++++++++++ + tests/qemu-iotests/033.out | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 43 insertions(+) + +diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033 +index 4008f10..a61d8ce 100755 +--- a/tests/qemu-iotests/033 ++++ b/tests/qemu-iotests/033 +@@ -78,6 +78,19 @@ for align in 512 4k; do + echo + echo "== verifying patterns (2) ==" + do_test $align "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io ++ ++ echo ++ echo "== rewriting unaligned zeroes ==" ++ do_test $align "write -P 0xb 0x0 0x1000" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "write -z 0x200 0x200" "$TEST_IMG" | _filter_qemu_io ++ ++ echo ++ echo "== verifying patterns (3) ==" ++ do_test $align "read -P 0xb 0x0 0x200" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "read -P 0x0 0x200 0x200" "$TEST_IMG" | _filter_qemu_io ++ do_test $align "read -P 0xb 0x400 0xc00" "$TEST_IMG" | _filter_qemu_io ++ ++ echo + done + + # success, all done +diff --git a/tests/qemu-iotests/033.out b/tests/qemu-iotests/033.out +index 344065f..6896d73 100644 +--- a/tests/qemu-iotests/033.out ++++ b/tests/qemu-iotests/033.out +@@ -27,6 +27,21 @@ wrote 65536/65536 bytes at offset 65536 + read 131072/131072 bytes at offset 1024 + 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + ++== rewriting unaligned zeroes == ++wrote 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 512/512 bytes at offset 512 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== verifying patterns (3) == ++read 512/512 bytes at offset 0 ++512 bytes, 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 3072/3072 bytes at offset 1024 ++3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++ + == preparing image == + wrote 1024/1024 bytes at offset 512 + 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -52,4 +67,19 @@ wrote 65536/65536 bytes at offset 65536 + == verifying patterns (2) == + read 131072/131072 bytes at offset 1024 + 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== rewriting unaligned zeroes == ++wrote 4096/4096 bytes at offset 0 ++4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 512/512 bytes at offset 512 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++== verifying patterns (3) == ++read 512/512 bytes at offset 0 ++512 bytes, 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 3072/3072 bytes at offset 1024 ++3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qtest-ide-test-disable-flush-test.patch b/SOURCES/kvm-qtest-ide-test-disable-flush-test.patch index 7624cff..200ab2e 100644 --- a/SOURCES/kvm-qtest-ide-test-disable-flush-test.patch +++ b/SOURCES/kvm-qtest-ide-test-disable-flush-test.patch @@ -1,23 +1,23 @@ -From 699e404550228859f73ce42f36c6da538e1b0fb1 Mon Sep 17 00:00:00 2001 -Message-Id: <699e404550228859f73ce42f36c6da538e1b0fb1.1445289321.git.jen@redhat.com> +From 228e49fabffa644ab7a6a03e98205f293115dc89 Mon Sep 17 00:00:00 2001 +Message-Id: <228e49fabffa644ab7a6a03e98205f293115dc89.1445029944.git.jen@redhat.com> From: John Snow -Date: Mon, 19 Oct 2015 17:58:34 -0400 +Date: Fri, 16 Oct 2015 16:26:24 -0500 Subject: [CHANGE] qtest/ide-test: disable flush-test To: rhvirt-patches@redhat.com, jen@redhat.com RH-Author: John Snow -Message-id: <1445277514-26179-2-git-send-email-jsnow@redhat.com> -Patchwork-id: 68184 -O-Subject: [RHEL-7.1.z qemu-kvm PATCH 1/1] qtest/ide-test: disable flush-test -Bugzilla: 1273098 -RH-Acked-by: Jeff Nelson -RH-Acked-by: Wei Huang +Message-id: <1445012784-22604-2-git-send-email-jsnow@redhat.com> +Patchwork-id: 68169 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/1] qtest/ide-test: disable flush-test +Bugzilla: 1270341 RH-Acked-by: Laszlo Ersek +RH-Acked-by: Wei Huang +RH-Acked-by: Jeff Nelson One of the tests downstream causes a race that can result in build -failures. For 7.3, we intend to fix the test properly, but for 7.1.z -and 7.2.*, we disable the test as a workaround. +failures. For 7.3, we intend to fix the test properly, but for 7.2, +we disable the test as a workaround. Signed-off-by: John Snow Signed-off-by: Jeff E. Nelson diff --git a/SOURCES/kvm-raw-posix-Fail-gracefully-if-no-working-alignment-is.patch b/SOURCES/kvm-raw-posix-Fail-gracefully-if-no-working-alignment-is.patch new file mode 100644 index 0000000..09e50c3 --- /dev/null +++ b/SOURCES/kvm-raw-posix-Fail-gracefully-if-no-working-alignment-is.patch @@ -0,0 +1,141 @@ +From ea0e0a4820d0dfa1227bd8351d89e9d55b25da44 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 17 Mar 2015 12:59:01 +0100 +Subject: [PATCH 12/16] raw-posix: Fail gracefully if no working alignment is + found + +Message-id: <1424365599-9801-3-git-send-email-stefanha@redhat.com> +Patchwork-id: 63913 +O-Subject: [RHEL-7.1 qemu-kvm PATCH 2/2] raw-posix: Fail gracefully if no working alignment is found +Bugzilla: 1184363 +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow +RH-Acked-by: Laszlo Ersek + +From: Kevin Wolf + +If qemu couldn't find out what O_DIRECT alignment to use with a given +file, it would run into assert(bdrv_opt_mem_align(bs) != 0); in block.c +and confuse users. This adds a more descriptive error message for such +cases. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit df26a35025427f34c1d4e5a8e51152371a5e231e) +Signed-off-by: Stefan Hajnoczi +--- + block/raw-posix.c | 35 +++++++++++++++++++++++++++-------- + 1 file changed, 27 insertions(+), 8 deletions(-) + +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 6a50856..af526ca 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -213,7 +213,7 @@ static int raw_normalize_devicepath(const char **filename) + } + #endif + +-static void raw_probe_alignment(BlockDriverState *bs) ++static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) + { + BDRVRawState *s = bs->opaque; + char *buf; +@@ -232,24 +232,24 @@ static void raw_probe_alignment(BlockDriverState *bs) + s->buf_align = 0; + + #ifdef BLKSSZGET +- if (ioctl(s->fd, BLKSSZGET, §or_size) >= 0) { ++ if (ioctl(fd, BLKSSZGET, §or_size) >= 0) { + bs->request_alignment = sector_size; + } + #endif + #ifdef DKIOCGETBLOCKSIZE +- if (ioctl(s->fd, DKIOCGETBLOCKSIZE, §or_size) >= 0) { ++ if (ioctl(fd, DKIOCGETBLOCKSIZE, §or_size) >= 0) { + bs->request_alignment = sector_size; + } + #endif + #ifdef DIOCGSECTORSIZE +- if (ioctl(s->fd, DIOCGSECTORSIZE, §or_size) >= 0) { ++ if (ioctl(fd, DIOCGSECTORSIZE, §or_size) >= 0) { + bs->request_alignment = sector_size; + } + #endif + #ifdef CONFIG_XFS + if (s->is_xfs) { + struct dioattr da; +- if (xfsctl(NULL, s->fd, XFS_IOC_DIOINFO, &da) >= 0) { ++ if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) { + bs->request_alignment = da.d_miniosz; + /* The kernel returns wrong information for d_mem */ + /* s->buf_align = da.d_mem; */ +@@ -262,7 +262,7 @@ static void raw_probe_alignment(BlockDriverState *bs) + size_t align; + buf = qemu_memalign(MAX_BLOCKSIZE, 2 * MAX_BLOCKSIZE); + for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) { +- if (pread(s->fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) { ++ if (pread(fd, buf + align, MAX_BLOCKSIZE, 0) >= 0) { + s->buf_align = align; + break; + } +@@ -274,13 +274,18 @@ static void raw_probe_alignment(BlockDriverState *bs) + size_t align; + buf = qemu_memalign(s->buf_align, MAX_BLOCKSIZE); + for (align = 512; align <= MAX_BLOCKSIZE; align <<= 1) { +- if (pread(s->fd, buf, align, 0) >= 0) { ++ if (pread(fd, buf, align, 0) >= 0) { + bs->request_alignment = align; + break; + } + } + qemu_vfree(buf); + } ++ ++ if (!s->buf_align || !bs->request_alignment) { ++ error_setg(errp, "Could not find working O_DIRECT alignment. " ++ "Try cache.direct=off."); ++ } + } + + static void raw_parse_flags(int bdrv_flags, int *open_flags) +@@ -459,6 +464,7 @@ static int raw_reopen_prepare(BDRVReopenState *state, + BDRVRawState *s; + BDRVRawReopenState *raw_s; + int ret = 0; ++ Error *local_err = NULL; + + assert(state != NULL); + assert(state->bs != NULL); +@@ -531,6 +537,19 @@ static int raw_reopen_prepare(BDRVReopenState *state, + ret = -1; + } + } ++ ++ /* Fail already reopen_prepare() if we can't get a working O_DIRECT ++ * alignment with the new fd. */ ++ if (raw_s->fd != -1) { ++ raw_probe_alignment(state->bs, raw_s->fd, &local_err); ++ if (local_err) { ++ qemu_close(raw_s->fd); ++ raw_s->fd = -1; ++ error_propagate(errp, local_err); ++ ret = -EINVAL; ++ } ++ } ++ + return ret; + } + +@@ -573,7 +592,7 @@ static int raw_refresh_limits(BlockDriverState *bs) + { + BDRVRawState *s = bs->opaque; + +- raw_probe_alignment(bs); ++ raw_probe_alignment(bs, s->fd, errp); + bs->bl.opt_mem_alignment = s->buf_align; + + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch b/SOURCES/kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch index 53483b8..7181046 100644 --- a/SOURCES/kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch +++ b/SOURCES/kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch @@ -1,13 +1,13 @@ -From ceffa7fb93c4ea570a0c854974a4993eedea52ca Mon Sep 17 00:00:00 2001 +From 5ec13dc4ed1c536de9711cb05af88609d073abf9 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:42 +0200 -Subject: [PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing +Subject: [PATCH 07/13] rtl8139: avoid nested ifs in IP header parsing (CVE-2015-5165) Message-id: <1438358388-10575-2-git-send-email-stefanha@redhat.com> Patchwork-id: 67236 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 1/7] rtl8139: avoid nested ifs in IP header parsing (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch b/SOURCES/kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch index f415886..8eb671f 100644 --- a/SOURCES/kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch +++ b/SOURCES/kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch @@ -1,12 +1,12 @@ -From 230b373704579a17a7a7e6890fe0dc1b789a2fa4 Mon Sep 17 00:00:00 2001 +From bea12592014d3371ca8d65fdf7cba2e84d3d46b7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:45 +0200 -Subject: [PATCH 4/7] rtl8139: check IP Header Length field (CVE-2015-5165) +Subject: [PATCH 10/13] rtl8139: check IP Header Length field (CVE-2015-5165) Message-id: <1438358388-10575-5-git-send-email-stefanha@redhat.com> Patchwork-id: 67239 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 4/7] rtl8139: check IP Header Length field (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch b/SOURCES/kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch index a9fa82a..546999f 100644 --- a/SOURCES/kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch +++ b/SOURCES/kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch @@ -1,12 +1,12 @@ -From 32e2f1ebf0d979c5ccc7e934ea9729e956d6aa52 Mon Sep 17 00:00:00 2001 +From 41ff6215085ee4118cad53b590be957143161f96 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:46 +0200 -Subject: [PATCH 5/7] rtl8139: check IP Total Length field (CVE-2015-5165) +Subject: [PATCH 11/13] rtl8139: check IP Total Length field (CVE-2015-5165) Message-id: <1438358388-10575-6-git-send-email-stefanha@redhat.com> Patchwork-id: 67240 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 5/7] rtl8139: check IP Total Length field (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch b/SOURCES/kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch index 9dfe885..df59a3b 100644 --- a/SOURCES/kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch +++ b/SOURCES/kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch @@ -1,12 +1,12 @@ -From a8cef763585fecc8b89d006efca0e000df923d36 Mon Sep 17 00:00:00 2001 +From 03a9670ae89e39fcfcd6b99ab66b4e4cab7c85b7 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:48 +0200 -Subject: [PATCH 7/7] rtl8139: check TCP Data Offset field (CVE-2015-5165) +Subject: [PATCH 13/13] rtl8139: check TCP Data Offset field (CVE-2015-5165) Message-id: <1438358388-10575-8-git-send-email-stefanha@redhat.com> Patchwork-id: 67242 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 7/7] rtl8139: check TCP Data Offset field (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch b/SOURCES/kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch index aaf4c06..f062488 100644 --- a/SOURCES/kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch +++ b/SOURCES/kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch @@ -1,13 +1,13 @@ -From 95ea90bc29b45f9b07b55c6cbb396fe854199079 Mon Sep 17 00:00:00 2001 +From fc8f8c54749bfeb7a4320875dc2bfd3565cf5ebe Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:43 +0200 -Subject: [PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement +Subject: [PATCH 08/13] rtl8139: drop tautologous if (ip) {...} statement (CVE-2015-5165) Message-id: <1438358388-10575-3-git-send-email-stefanha@redhat.com> Patchwork-id: 67238 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 2/7] rtl8139: drop tautologous if (ip) {...} statement (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch b/SOURCES/kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch index 2e52dd6..1e14729 100644 --- a/SOURCES/kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch +++ b/SOURCES/kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch @@ -1,13 +1,13 @@ -From 305025fe1852b99fcd84b6cd75ed7392d4f49efc Mon Sep 17 00:00:00 2001 +From 87c927af369a24b466b9429e9c785219ea718863 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:44 +0200 -Subject: [PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header +Subject: [PATCH 09/13] rtl8139: skip offload on short Ethernet/IP header (CVE-2015-5165) Message-id: <1438358388-10575-4-git-send-email-stefanha@redhat.com> Patchwork-id: 67237 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 3/7] rtl8139: skip offload on short Ethernet/IP header (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch b/SOURCES/kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch index b722c87..05fa035 100644 --- a/SOURCES/kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch +++ b/SOURCES/kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch @@ -1,12 +1,13 @@ -From 7940931aeb97ec1b27fade4f7863418a4afd828f Mon Sep 17 00:00:00 2001 +From 62f1eddbc1e0261ff18e5a0dd0e0db23a93e8d4e Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 31 Jul 2015 15:59:47 +0200 -Subject: [PATCH 6/7] rtl8139: skip offload on short TCP header (CVE-2015-5165) +Subject: [PATCH 12/13] rtl8139: skip offload on short TCP header + (CVE-2015-5165) Message-id: <1438358388-10575-7-git-send-email-stefanha@redhat.com> Patchwork-id: 67241 O-Subject: [RHEL-7.1.z qemu-kvm EMBARGOED PATCH 6/7] rtl8139: skip offload on short TCP header (CVE-2015-5165) -Bugzilla: 1248764 +Bugzilla: 1248766 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Xiao Wang RH-Acked-by: Laszlo Ersek diff --git a/SOURCES/kvm-scsi-disk-fix-cmd.mode-field-typo.patch b/SOURCES/kvm-scsi-disk-fix-cmd.mode-field-typo.patch new file mode 100644 index 0000000..f5935cd --- /dev/null +++ b/SOURCES/kvm-scsi-disk-fix-cmd.mode-field-typo.patch @@ -0,0 +1,45 @@ +From 684c8889083b1479d64c7a04b2d0dd8b9961d46d Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 3 Aug 2015 16:51:20 +0200 +Subject: [PATCH 06/13] scsi-disk: fix cmd.mode field typo + +Message-id: <1438620680-24121-3-git-send-email-stefanha@redhat.com> +Patchwork-id: 67256 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] scsi-disk: fix cmd.mode field typo +Bugzilla: 1249718 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Fam Zheng +RH-Acked-by: Paolo Bonzini + +The cmd.xfer field is the data length. The cmd.mode field is the data +transfer direction. + +scsi_handle_rw_error() was using the wrong error policy for read +requests. + +Signed-off-by: Stefan Hajnoczi +Message-Id: <1438262173-11546-3-git-send-email-stefanha@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit c85a7a0057ca454607a40cde991d495e0deec34d) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Miroslav Rezanina +--- + 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 50b7910..8a8b0ab 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -413,7 +413,7 @@ static void scsi_read_data(SCSIRequest *req) + */ + static int scsi_handle_rw_error(SCSIDiskReq *r, int error) + { +- bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV); ++ bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV); + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-seccomp-add-timerfd_create-and-timerfd_settime-to-th.patch b/SOURCES/kvm-seccomp-add-timerfd_create-and-timerfd_settime-to-th.patch new file mode 100644 index 0000000..77250ce --- /dev/null +++ b/SOURCES/kvm-seccomp-add-timerfd_create-and-timerfd_settime-to-th.patch @@ -0,0 +1,88 @@ +From 982a3d6d0569bed08ee7d31380271abe69d836b4 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 30 Apr 2015 10:31:57 +0200 +Subject: [PATCH 1/4] seccomp: add timerfd_create and timerfd_settime to the + whitelist + +Message-id: <1430389917-29237-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 64959 +O-Subject: [RHEL-7.1 qemu-kvm PATCH 1/1] seccomp: add timerfd_create and timerfd_settime to the whitelist +Bugzilla: 1185737 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Markus Armbruster + +From: Felix Geyer + +libusb calls timerfd_create() and timerfd_settime() when it's built with +timerfd support. + +Command to reproduce: + + -device usb-host,hostbus=1,hostaddr=3,id=hostdev0 + +Log messages: + +audit(1390730418.924:135): auid=4294967295 uid=121 gid=103 ses=4294967295 + pid=5232 comm="qemu-system-x86" sig=31 syscall=283 + compat=0 ip=0x7f2b0f4e96a7 code=0x0 +audit(1390733100.580:142): auid=4294967295 uid=121 gid=103 ses=4294967295 + pid=16909 comm="qemu-system-x86" sig=31 syscall=286 + compat=0 ip=0x7f03513a06da code=0x0 + +Reading a few hundred MB from a USB drive on x86_64 shows this syscall distribution. +Therefore the timerfd_settime priority is set to 242. + + calls syscall + --------- ---------------- + 5303600 write + 2240554 read + 2167030 ppoll + 2134828 ioctl + 704023 timerfd_settime + 689105 poll + 83122 futex + 803 writev + 476 rt_sigprocmask + 287 recvmsg + 178 brk + +Signed-off-by: Felix Geyer +Signed-off-by: Eduardo Otubo +(cherry picked from commit 84397618529f920bea45d0bab22ec097766244fc) +Signed-off-by: Miroslav Rezanina + +Conflicts: + qemu-seccomp.c +--- + qemu-seccomp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) +--- + qemu-seccomp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/qemu-seccomp.c b/qemu-seccomp.c +index 59cae8e..5e60fce 100644 +--- a/qemu-seccomp.c ++++ b/qemu-seccomp.c +@@ -154,6 +154,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { + { SCMP_SYS(getsockname), 242 }, + { SCMP_SYS(getpeername), 242 }, + { SCMP_SYS(accept4), 242 }, ++ { SCMP_SYS(timerfd_settime), 242 }, + { SCMP_SYS(newfstatat), 241 }, + { SCMP_SYS(shutdown), 241 }, + { SCMP_SYS(getsockopt), 241 }, +@@ -246,7 +247,8 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { + { SCMP_SYS(shmctl), 240 }, + { SCMP_SYS(mlock), 240 }, + { SCMP_SYS(munlock), 240 }, +- { SCMP_SYS(semctl), 240 } ++ { SCMP_SYS(semctl), 240 }, ++ { SCMP_SYS(timerfd_create), 240 }, + }; + + int seccomp_start(void) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-serial-reset-state-at-startup.patch b/SOURCES/kvm-serial-reset-state-at-startup.patch new file mode 100644 index 0000000..b7a71fb --- /dev/null +++ b/SOURCES/kvm-serial-reset-state-at-startup.patch @@ -0,0 +1,39 @@ +From 3f947faca0fb91f4b1104862f7c71bf3f6bd5d48 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 7 Aug 2015 15:24:38 +0200 +Subject: [PATCH 1/2] serial: reset state at startup + +Message-id: <1438961078-13625-1-git-send-email-pbonzini@redhat.com> +Patchwork-id: 67393 +O-Subject: [RHEL7.2 qemu-kvm-rhev PATCH] serial: reset state at startup +Bugzilla: 922014 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Andrew Jones +RH-Acked-by: Laszlo Ersek + +When a serial port is started, its initial state is all zero. Make +it consistent with reset state instead. + +Signed-off-by: Paolo Bonzini +Upstream commit 4df7961faaa317d57e873ecdec58422d3f979336 + +Signed-off-by: Miroslav Rezanina +--- + hw/char/serial.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/char/serial.c b/hw/char/serial.c +index 0c472e2..2383c31 100644 +--- a/hw/char/serial.c ++++ b/hw/char/serial.c +@@ -685,6 +685,7 @@ void serial_init_core(SerialState *s) + + qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1, + serial_event, s); ++ serial_reset(s); + } + + void serial_exit_core(SerialState *s) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-socket-shutdown.patch b/SOURCES/kvm-socket-shutdown.patch new file mode 100644 index 0000000..38ad378 --- /dev/null +++ b/SOURCES/kvm-socket-shutdown.patch @@ -0,0 +1,151 @@ +From da3039bc7ec4fda6719be3bdd10f4b0fdaceb17a Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Fri, 16 Jan 2015 17:35:35 +0100 +Subject: [PATCH 03/16] socket shutdown + +Message-id: <1421429737-23581-2-git-send-email-dgilbert@redhat.com> +Patchwork-id: 63332 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/3] socket shutdown +Bugzilla: 1086168 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek + +From: "Dr. David Alan Gilbert" + +Add QEMUFile interface to allow a socket to be 'shut down' - i.e. any +reads/writes will fail (and any blocking read/write will be woken). + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Paolo Bonzini +Reviewed-by: Amit Shah +Signed-off-by: Amit Shah +(cherry picked from commit e1a8c9b67fc97d293211773edcae9e8e2f3367ab) +Signed-off-by: Miroslav Rezanina + +Conflicts: + include/migration/qemu-file.h + migration/qemu-file-unix.c + migration/qemu-file.c + + Because we split qemu-file.c out of savevm and moved it +--- + include/migration/qemu-file.h | 10 ++++++++++ + include/qemu/sockets.h | 7 +++++++ + savevm.c | 33 +++++++++++++++++++++++++++++---- + 3 files changed, 46 insertions(+), 4 deletions(-) + +diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h +index 0f757fb..032de47 100644 +--- a/include/migration/qemu-file.h ++++ b/include/migration/qemu-file.h +@@ -82,6 +82,14 @@ typedef size_t (QEMURamSaveFunc)(QEMUFile *f, void *opaque, + size_t size, + int *bytes_sent); + ++/* ++ * Stop any read or write (depending on flags) on the underlying ++ * transport on the QEMUFile. ++ * Existing blocking reads/writes must be woken ++ * Returns 0 on success, -err on error ++ */ ++typedef int (QEMUFileShutdownFunc)(void *opaque, bool rd, bool wr); ++ + typedef struct QEMUFileOps { + QEMUFilePutBufferFunc *put_buffer; + QEMUFileGetBufferFunc *get_buffer; +@@ -92,6 +100,7 @@ typedef struct QEMUFileOps { + QEMURamHookFunc *after_ram_iterate; + QEMURamHookFunc *hook_ram_load; + QEMURamSaveFunc *save_page; ++ QEMUFileShutdownFunc *shut_down; + } QEMUFileOps; + + QEMUFile *qemu_fopen_ops(void *opaque, const QEMUFileOps *ops); +@@ -141,6 +150,7 @@ void qemu_file_reset_rate_limit(QEMUFile *f); + void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); + int64_t qemu_file_get_rate_limit(QEMUFile *f); + int qemu_file_get_error(QEMUFile *f); ++int qemu_file_shutdown(QEMUFile *f); + void qemu_fflush(QEMUFile *f); + + static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) +diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h +index c5174d7..729ff52 100644 +--- a/include/qemu/sockets.h ++++ b/include/qemu/sockets.h +@@ -42,6 +42,13 @@ void qemu_set_nonblock(int fd); + int send_all(int fd, const void *buf, int len1); + int recv_all(int fd, void *buf, int len1, bool single_read); + ++#ifdef WIN32 ++/* Windows has different names for the same constants with the same values */ ++#define SHUT_RD 0 ++#define SHUT_WR 1 ++#define SHUT_RDWR 2 ++#endif ++ + /* callback function for nonblocking connect + * valid fd on success, negative error code on failure + */ +diff --git a/savevm.c b/savevm.c +index 963dc7d..731d5c0 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -204,6 +204,17 @@ static int socket_close(void *opaque) + return 0; + } + ++static int socket_shutdown(void *opaque, bool rd, bool wr) ++{ ++ QEMUFileSocket *s = opaque; ++ ++ if (shutdown(s->fd, rd ? (wr ? SHUT_RDWR : SHUT_RD) : SHUT_WR)) { ++ return -errno; ++ } else { ++ return 0; ++ } ++} ++ + static int stdio_get_fd(void *opaque) + { + QEMUFileStdio *s = opaque; +@@ -448,17 +459,31 @@ QEMUFile *qemu_fdopen(int fd, const char *mode) + } + + static const QEMUFileOps socket_read_ops = { +- .get_fd = socket_get_fd, ++ .get_fd = socket_get_fd, + .get_buffer = socket_get_buffer, +- .close = socket_close ++ .close = socket_close, ++ .shut_down = socket_shutdown + }; + + static const QEMUFileOps socket_write_ops = { +- .get_fd = socket_get_fd, ++ .get_fd = socket_get_fd, + .writev_buffer = socket_writev_buffer, +- .close = socket_close ++ .close = socket_close, ++ .shut_down = socket_shutdown + }; + ++/* ++ * Stop a file from being read/written - not all backing files can do this ++ * typically only sockets can. ++ */ ++int qemu_file_shutdown(QEMUFile *f) ++{ ++ if (!f->ops->shut_down) { ++ return -ENOSYS; ++ } ++ return f->ops->shut_down(f->opaque, true, true); ++} ++ + bool qemu_file_mode_is_not_valid(const char *mode) + { + if (mode == NULL || +-- +1.8.3.1 + diff --git a/SOURCES/kvm-spice-display-fix-segfault-in-qemu_spice_create_upda.patch b/SOURCES/kvm-spice-display-fix-segfault-in-qemu_spice_create_upda.patch new file mode 100644 index 0000000..3a94d53 --- /dev/null +++ b/SOURCES/kvm-spice-display-fix-segfault-in-qemu_spice_create_upda.patch @@ -0,0 +1,60 @@ +From 25bafb9e1c938197a716d21010ab532aa85b82bf Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 11 Jun 2015 15:17:36 +0200 +Subject: [PATCH 4/4] spice-display: fix segfault in qemu_spice_create_update + +Message-id: <1434035856-9153-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 65858 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/1] spice-display: fix segfault in qemu_spice_create_update +Bugzilla: 1230808 +RH-Acked-by: Bandan Das +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Laszlo Ersek + +Although it is pretty unusual the stride for the guest image and the +mirror image maintained by spice-display can be different. So use +separate variables for them. + +Cc: qemu-stable@nongnu.org +Reported-by: perrier vincent +Signed-off-by: Gerd Hoffmann +(cherry picked from commit c6e484707f28b3e115e64122a0570f6b3c585489) +Signed-off-by: Miroslav Rezanina +--- + ui/spice-display.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/ui/spice-display.c b/ui/spice-display.c +index dc8be8a..d29d2ab 100644 +--- a/ui/spice-display.c ++++ b/ui/spice-display.c +@@ -199,7 +199,7 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) + static const int blksize = 32; + int blocks = (surface_width(ssd->ds) + blksize - 1) / blksize; + int dirty_top[blocks]; +- int y, yoff, x, xoff, blk, bw; ++ int y, yoff1, yoff2, x, xoff, blk, bw; + int bpp = surface_bytes_per_pixel(ssd->ds); + uint8_t *guest, *mirror; + +@@ -220,13 +220,14 @@ static void qemu_spice_create_update(SimpleSpiceDisplay *ssd) + guest = surface_data(ssd->ds); + mirror = (void *)pixman_image_get_data(ssd->mirror); + for (y = ssd->dirty.top; y < ssd->dirty.bottom; y++) { +- yoff = y * surface_stride(ssd->ds); ++ yoff1 = y * surface_stride(ssd->ds); ++ yoff2 = y * pixman_image_get_stride(ssd->mirror); + for (x = ssd->dirty.left; x < ssd->dirty.right; x += blksize) { + xoff = x * bpp; + blk = x / blksize; + bw = MIN(blksize, ssd->dirty.right - x); +- if (memcmp(guest + yoff + xoff, +- mirror + yoff + xoff, ++ if (memcmp(guest + yoff1 + xoff, ++ mirror + yoff2 + xoff, + bw * bpp) == 0) { + if (dirty_top[blk] != -1) { + QXLRect update = { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ssh-Don-t-crash-if-either-host-or-path-is-not-specif.patch b/SOURCES/kvm-ssh-Don-t-crash-if-either-host-or-path-is-not-specif.patch new file mode 100644 index 0000000..90e1e93 --- /dev/null +++ b/SOURCES/kvm-ssh-Don-t-crash-if-either-host-or-path-is-not-specif.patch @@ -0,0 +1,70 @@ +From 566d5a879e639f0dd5beacf49e5fcb03691aac09 Mon Sep 17 00:00:00 2001 +From: Richard Jones +Date: Mon, 8 Jun 2015 11:57:00 +0200 +Subject: [PATCH 07/30] ssh: Don't crash if either host or path is not + specified. + +Message-id: <1433764620-20506-7-git-send-email-rjones@redhat.com> +Patchwork-id: 65481 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 6/6] ssh: Don't crash if either host or path is not specified. +Bugzilla: 1226683 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +From: "Richard W.M. Jones" + +$ ./qemu-img create -f qcow2 overlay \ + -b 'json: { "file.driver":"ssh", + "file.host":"localhost", + "file.host_key_check":"no" }' +qemu-img: qobject/qdict.c:193: qdict_get_obj: Assertion `obj != ((void *)0)' failed. +Aborted + +A similar crash also happens if the file.host field is omitted. + +https://bugzilla.redhat.com/show_bug.cgi?id=1147343 + +Bug found and reported by Jun Li. + +Signed-off-by: Richard W.M. Jones +Reviewed-by: Gonglei +Signed-off-by: Stefan Hajnoczi + +Upstream-status: 18fe46d79a6de61cb2c379fb610d834ef658d84b +Signed-off-by: Miroslav Rezanina +--- + block/ssh.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/block/ssh.c b/block/ssh.c +index 3b4d9e7..b00ff7f 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -517,6 +517,11 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + const char *host, *user, *path, *host_key_check; + int port; + ++ if (!qdict_haskey(options, "host")) { ++ ret = -EINVAL; ++ error_setg(errp, "No hostname was specified"); ++ goto err; ++ } + host = qdict_get_str(options, "host"); + + if (qdict_haskey(options, "port")) { +@@ -525,6 +530,11 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + port = 22; + } + ++ if (!qdict_haskey(options, "path")) { ++ ret = -EINVAL; ++ error_setg(errp, "No path was specified"); ++ goto err; ++ } + path = qdict_get_str(options, "path"); + + if (qdict_haskey(options, "user")) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Add-mpx-CPU-feature-name.patch b/SOURCES/kvm-target-i386-Add-mpx-CPU-feature-name.patch new file mode 100644 index 0000000..d808848 --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-mpx-CPU-feature-name.patch @@ -0,0 +1,42 @@ +From 60fe9056e610b5ee15b4715586d816c099060f41 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:27 +0200 +Subject: [PATCH 07/10] target-i386: Add "mpx" CPU feature name + +Message-id: <1435260689-9556-7-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66503 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 6/8] target-i386: Add "mpx" CPU feature name +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +Migration support for MPX is already implemented (commit +79e9ebebbf2a00c46fcedb6dc7dd5e12bbd30216), so we can add it to the list +of known feature names. + +Signed-off-by: Eduardo Habkost +Signed-off-by: Paolo Bonzini +(cherry picked from commit 5bd8ff07e65d066f1e90f05d49ee634f3ccd2664) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 96af1bf..fe60c33 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -145,7 +145,7 @@ static const char *svm_feature_name[] = { + + static const char *cpuid_7_0_ebx_feature_name[] = { + "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", +- "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL, ++ "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL, + NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Avoid-shifting-left-into-sign-bit.patch b/SOURCES/kvm-target-i386-Avoid-shifting-left-into-sign-bit.patch new file mode 100644 index 0000000..a9a92c1 --- /dev/null +++ b/SOURCES/kvm-target-i386-Avoid-shifting-left-into-sign-bit.patch @@ -0,0 +1,399 @@ +From ded1f83456d03cef5f99abe18a6c7568b0ecd656 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:28 +0200 +Subject: [PATCH 08/10] target-i386: Avoid shifting left into sign bit + +Message-id: <1435260689-9556-8-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66504 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 7/8] target-i386: Avoid shifting left into sign bit +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: Peter Maydell + +Add 'U' suffixes where necessary to avoid (1 << 31) which +shifts left into the sign bit, which is undefined behaviour. +Add the suffix also for other constants in the same groupings +even if they don't shift into bit 31, for consistency. + +Signed-off-by: Peter Maydell +Signed-off-by: Michael Tokarev +(cherry picked from commit 2cd49cbfab0dd294de421893048ab614518fa263) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.h | 334 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 167 insertions(+), 167 deletions(-) + +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 715ba63..fc1e42e 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -194,35 +194,35 @@ + #define CR0_PE_SHIFT 0 + #define CR0_MP_SHIFT 1 + +-#define CR0_PE_MASK (1 << 0) +-#define CR0_MP_MASK (1 << 1) +-#define CR0_EM_MASK (1 << 2) +-#define CR0_TS_MASK (1 << 3) +-#define CR0_ET_MASK (1 << 4) +-#define CR0_NE_MASK (1 << 5) +-#define CR0_WP_MASK (1 << 16) +-#define CR0_AM_MASK (1 << 18) +-#define CR0_PG_MASK (1 << 31) +- +-#define CR4_VME_MASK (1 << 0) +-#define CR4_PVI_MASK (1 << 1) +-#define CR4_TSD_MASK (1 << 2) +-#define CR4_DE_MASK (1 << 3) +-#define CR4_PSE_MASK (1 << 4) +-#define CR4_PAE_MASK (1 << 5) +-#define CR4_MCE_MASK (1 << 6) +-#define CR4_PGE_MASK (1 << 7) +-#define CR4_PCE_MASK (1 << 8) ++#define CR0_PE_MASK (1U << 0) ++#define CR0_MP_MASK (1U << 1) ++#define CR0_EM_MASK (1U << 2) ++#define CR0_TS_MASK (1U << 3) ++#define CR0_ET_MASK (1U << 4) ++#define CR0_NE_MASK (1U << 5) ++#define CR0_WP_MASK (1U << 16) ++#define CR0_AM_MASK (1U << 18) ++#define CR0_PG_MASK (1U << 31) ++ ++#define CR4_VME_MASK (1U << 0) ++#define CR4_PVI_MASK (1U << 1) ++#define CR4_TSD_MASK (1U << 2) ++#define CR4_DE_MASK (1U << 3) ++#define CR4_PSE_MASK (1U << 4) ++#define CR4_PAE_MASK (1U << 5) ++#define CR4_MCE_MASK (1U << 6) ++#define CR4_PGE_MASK (1U << 7) ++#define CR4_PCE_MASK (1U << 8) + #define CR4_OSFXSR_SHIFT 9 +-#define CR4_OSFXSR_MASK (1 << CR4_OSFXSR_SHIFT) +-#define CR4_OSXMMEXCPT_MASK (1 << 10) +-#define CR4_VMXE_MASK (1 << 13) +-#define CR4_SMXE_MASK (1 << 14) +-#define CR4_FSGSBASE_MASK (1 << 16) +-#define CR4_PCIDE_MASK (1 << 17) +-#define CR4_OSXSAVE_MASK (1 << 18) +-#define CR4_SMEP_MASK (1 << 20) +-#define CR4_SMAP_MASK (1 << 21) ++#define CR4_OSFXSR_MASK (1U << CR4_OSFXSR_SHIFT) ++#define CR4_OSXMMEXCPT_MASK (1U << 10) ++#define CR4_VMXE_MASK (1U << 13) ++#define CR4_SMXE_MASK (1U << 14) ++#define CR4_FSGSBASE_MASK (1U << 16) ++#define CR4_PCIDE_MASK (1U << 17) ++#define CR4_OSXSAVE_MASK (1U << 18) ++#define CR4_SMEP_MASK (1U << 20) ++#define CR4_SMAP_MASK (1U << 21) + + #define DR6_BD (1 << 13) + #define DR6_BS (1 << 14) +@@ -408,96 +408,96 @@ typedef enum FeatureWord { + typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + /* cpuid_features bits */ +-#define CPUID_FP87 (1 << 0) +-#define CPUID_VME (1 << 1) +-#define CPUID_DE (1 << 2) +-#define CPUID_PSE (1 << 3) +-#define CPUID_TSC (1 << 4) +-#define CPUID_MSR (1 << 5) +-#define CPUID_PAE (1 << 6) +-#define CPUID_MCE (1 << 7) +-#define CPUID_CX8 (1 << 8) +-#define CPUID_APIC (1 << 9) +-#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ +-#define CPUID_MTRR (1 << 12) +-#define CPUID_PGE (1 << 13) +-#define CPUID_MCA (1 << 14) +-#define CPUID_CMOV (1 << 15) +-#define CPUID_PAT (1 << 16) +-#define CPUID_PSE36 (1 << 17) +-#define CPUID_PN (1 << 18) +-#define CPUID_CLFLUSH (1 << 19) +-#define CPUID_DTS (1 << 21) +-#define CPUID_ACPI (1 << 22) +-#define CPUID_MMX (1 << 23) +-#define CPUID_FXSR (1 << 24) +-#define CPUID_SSE (1 << 25) +-#define CPUID_SSE2 (1 << 26) +-#define CPUID_SS (1 << 27) +-#define CPUID_HT (1 << 28) +-#define CPUID_TM (1 << 29) +-#define CPUID_IA64 (1 << 30) +-#define CPUID_PBE (1 << 31) +- +-#define CPUID_EXT_SSE3 (1 << 0) +-#define CPUID_EXT_PCLMULQDQ (1 << 1) +-#define CPUID_EXT_DTES64 (1 << 2) +-#define CPUID_EXT_MONITOR (1 << 3) +-#define CPUID_EXT_DSCPL (1 << 4) +-#define CPUID_EXT_VMX (1 << 5) +-#define CPUID_EXT_SMX (1 << 6) +-#define CPUID_EXT_EST (1 << 7) +-#define CPUID_EXT_TM2 (1 << 8) +-#define CPUID_EXT_SSSE3 (1 << 9) +-#define CPUID_EXT_CID (1 << 10) +-#define CPUID_EXT_FMA (1 << 12) +-#define CPUID_EXT_CX16 (1 << 13) +-#define CPUID_EXT_XTPR (1 << 14) +-#define CPUID_EXT_PDCM (1 << 15) +-#define CPUID_EXT_PCID (1 << 17) +-#define CPUID_EXT_DCA (1 << 18) +-#define CPUID_EXT_SSE41 (1 << 19) +-#define CPUID_EXT_SSE42 (1 << 20) +-#define CPUID_EXT_X2APIC (1 << 21) +-#define CPUID_EXT_MOVBE (1 << 22) +-#define CPUID_EXT_POPCNT (1 << 23) +-#define CPUID_EXT_TSC_DEADLINE_TIMER (1 << 24) +-#define CPUID_EXT_AES (1 << 25) +-#define CPUID_EXT_XSAVE (1 << 26) +-#define CPUID_EXT_OSXSAVE (1 << 27) +-#define CPUID_EXT_AVX (1 << 28) +-#define CPUID_EXT_F16C (1 << 29) +-#define CPUID_EXT_RDRAND (1 << 30) +-#define CPUID_EXT_HYPERVISOR (1 << 31) +- +-#define CPUID_EXT2_FPU (1 << 0) +-#define CPUID_EXT2_VME (1 << 1) +-#define CPUID_EXT2_DE (1 << 2) +-#define CPUID_EXT2_PSE (1 << 3) +-#define CPUID_EXT2_TSC (1 << 4) +-#define CPUID_EXT2_MSR (1 << 5) +-#define CPUID_EXT2_PAE (1 << 6) +-#define CPUID_EXT2_MCE (1 << 7) +-#define CPUID_EXT2_CX8 (1 << 8) +-#define CPUID_EXT2_APIC (1 << 9) +-#define CPUID_EXT2_SYSCALL (1 << 11) +-#define CPUID_EXT2_MTRR (1 << 12) +-#define CPUID_EXT2_PGE (1 << 13) +-#define CPUID_EXT2_MCA (1 << 14) +-#define CPUID_EXT2_CMOV (1 << 15) +-#define CPUID_EXT2_PAT (1 << 16) +-#define CPUID_EXT2_PSE36 (1 << 17) +-#define CPUID_EXT2_MP (1 << 19) +-#define CPUID_EXT2_NX (1 << 20) +-#define CPUID_EXT2_MMXEXT (1 << 22) +-#define CPUID_EXT2_MMX (1 << 23) +-#define CPUID_EXT2_FXSR (1 << 24) +-#define CPUID_EXT2_FFXSR (1 << 25) +-#define CPUID_EXT2_PDPE1GB (1 << 26) +-#define CPUID_EXT2_RDTSCP (1 << 27) +-#define CPUID_EXT2_LM (1 << 29) +-#define CPUID_EXT2_3DNOWEXT (1 << 30) +-#define CPUID_EXT2_3DNOW (1 << 31) ++#define CPUID_FP87 (1U << 0) ++#define CPUID_VME (1U << 1) ++#define CPUID_DE (1U << 2) ++#define CPUID_PSE (1U << 3) ++#define CPUID_TSC (1U << 4) ++#define CPUID_MSR (1U << 5) ++#define CPUID_PAE (1U << 6) ++#define CPUID_MCE (1U << 7) ++#define CPUID_CX8 (1U << 8) ++#define CPUID_APIC (1U << 9) ++#define CPUID_SEP (1U << 11) /* sysenter/sysexit */ ++#define CPUID_MTRR (1U << 12) ++#define CPUID_PGE (1U << 13) ++#define CPUID_MCA (1U << 14) ++#define CPUID_CMOV (1U << 15) ++#define CPUID_PAT (1U << 16) ++#define CPUID_PSE36 (1U << 17) ++#define CPUID_PN (1U << 18) ++#define CPUID_CLFLUSH (1U << 19) ++#define CPUID_DTS (1U << 21) ++#define CPUID_ACPI (1U << 22) ++#define CPUID_MMX (1U << 23) ++#define CPUID_FXSR (1U << 24) ++#define CPUID_SSE (1U << 25) ++#define CPUID_SSE2 (1U << 26) ++#define CPUID_SS (1U << 27) ++#define CPUID_HT (1U << 28) ++#define CPUID_TM (1U << 29) ++#define CPUID_IA64 (1U << 30) ++#define CPUID_PBE (1U << 31) ++ ++#define CPUID_EXT_SSE3 (1U << 0) ++#define CPUID_EXT_PCLMULQDQ (1U << 1) ++#define CPUID_EXT_DTES64 (1U << 2) ++#define CPUID_EXT_MONITOR (1U << 3) ++#define CPUID_EXT_DSCPL (1U << 4) ++#define CPUID_EXT_VMX (1U << 5) ++#define CPUID_EXT_SMX (1U << 6) ++#define CPUID_EXT_EST (1U << 7) ++#define CPUID_EXT_TM2 (1U << 8) ++#define CPUID_EXT_SSSE3 (1U << 9) ++#define CPUID_EXT_CID (1U << 10) ++#define CPUID_EXT_FMA (1U << 12) ++#define CPUID_EXT_CX16 (1U << 13) ++#define CPUID_EXT_XTPR (1U << 14) ++#define CPUID_EXT_PDCM (1U << 15) ++#define CPUID_EXT_PCID (1U << 17) ++#define CPUID_EXT_DCA (1U << 18) ++#define CPUID_EXT_SSE41 (1U << 19) ++#define CPUID_EXT_SSE42 (1U << 20) ++#define CPUID_EXT_X2APIC (1U << 21) ++#define CPUID_EXT_MOVBE (1U << 22) ++#define CPUID_EXT_POPCNT (1U << 23) ++#define CPUID_EXT_TSC_DEADLINE_TIMER (1U << 24) ++#define CPUID_EXT_AES (1U << 25) ++#define CPUID_EXT_XSAVE (1U << 26) ++#define CPUID_EXT_OSXSAVE (1U << 27) ++#define CPUID_EXT_AVX (1U << 28) ++#define CPUID_EXT_F16C (1U << 29) ++#define CPUID_EXT_RDRAND (1U << 30) ++#define CPUID_EXT_HYPERVISOR (1U << 31) ++ ++#define CPUID_EXT2_FPU (1U << 0) ++#define CPUID_EXT2_VME (1U << 1) ++#define CPUID_EXT2_DE (1U << 2) ++#define CPUID_EXT2_PSE (1U << 3) ++#define CPUID_EXT2_TSC (1U << 4) ++#define CPUID_EXT2_MSR (1U << 5) ++#define CPUID_EXT2_PAE (1U << 6) ++#define CPUID_EXT2_MCE (1U << 7) ++#define CPUID_EXT2_CX8 (1U << 8) ++#define CPUID_EXT2_APIC (1U << 9) ++#define CPUID_EXT2_SYSCALL (1U << 11) ++#define CPUID_EXT2_MTRR (1U << 12) ++#define CPUID_EXT2_PGE (1U << 13) ++#define CPUID_EXT2_MCA (1U << 14) ++#define CPUID_EXT2_CMOV (1U << 15) ++#define CPUID_EXT2_PAT (1U << 16) ++#define CPUID_EXT2_PSE36 (1U << 17) ++#define CPUID_EXT2_MP (1U << 19) ++#define CPUID_EXT2_NX (1U << 20) ++#define CPUID_EXT2_MMXEXT (1U << 22) ++#define CPUID_EXT2_MMX (1U << 23) ++#define CPUID_EXT2_FXSR (1U << 24) ++#define CPUID_EXT2_FFXSR (1U << 25) ++#define CPUID_EXT2_PDPE1GB (1U << 26) ++#define CPUID_EXT2_RDTSCP (1U << 27) ++#define CPUID_EXT2_LM (1U << 29) ++#define CPUID_EXT2_3DNOWEXT (1U << 30) ++#define CPUID_EXT2_3DNOW (1U << 31) + + /* CPUID[8000_0001].EDX bits that are aliase of CPUID[1].EDX bits on AMD CPUs */ + #define CPUID_EXT2_AMD_ALIASES (CPUID_EXT2_FPU | CPUID_EXT2_VME | \ +@@ -510,53 +510,53 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | \ + CPUID_EXT2_MMX | CPUID_EXT2_FXSR) + +-#define CPUID_EXT3_LAHF_LM (1 << 0) +-#define CPUID_EXT3_CMP_LEG (1 << 1) +-#define CPUID_EXT3_SVM (1 << 2) +-#define CPUID_EXT3_EXTAPIC (1 << 3) +-#define CPUID_EXT3_CR8LEG (1 << 4) +-#define CPUID_EXT3_ABM (1 << 5) +-#define CPUID_EXT3_SSE4A (1 << 6) +-#define CPUID_EXT3_MISALIGNSSE (1 << 7) +-#define CPUID_EXT3_3DNOWPREFETCH (1 << 8) +-#define CPUID_EXT3_OSVW (1 << 9) +-#define CPUID_EXT3_IBS (1 << 10) +-#define CPUID_EXT3_XOP (1 << 11) +-#define CPUID_EXT3_SKINIT (1 << 12) +-#define CPUID_EXT3_WDT (1 << 13) +-#define CPUID_EXT3_LWP (1 << 15) +-#define CPUID_EXT3_FMA4 (1 << 16) +-#define CPUID_EXT3_TCE (1 << 17) +-#define CPUID_EXT3_NODEID (1 << 19) +-#define CPUID_EXT3_TBM (1 << 21) +-#define CPUID_EXT3_TOPOEXT (1 << 22) +-#define CPUID_EXT3_PERFCORE (1 << 23) +-#define CPUID_EXT3_PERFNB (1 << 24) +- +-#define CPUID_SVM_NPT (1 << 0) +-#define CPUID_SVM_LBRV (1 << 1) +-#define CPUID_SVM_SVMLOCK (1 << 2) +-#define CPUID_SVM_NRIPSAVE (1 << 3) +-#define CPUID_SVM_TSCSCALE (1 << 4) +-#define CPUID_SVM_VMCBCLEAN (1 << 5) +-#define CPUID_SVM_FLUSHASID (1 << 6) +-#define CPUID_SVM_DECODEASSIST (1 << 7) +-#define CPUID_SVM_PAUSEFILTER (1 << 10) +-#define CPUID_SVM_PFTHRESHOLD (1 << 12) +- +-#define CPUID_7_0_EBX_FSGSBASE (1 << 0) +-#define CPUID_7_0_EBX_BMI1 (1 << 3) +-#define CPUID_7_0_EBX_HLE (1 << 4) +-#define CPUID_7_0_EBX_AVX2 (1 << 5) +-#define CPUID_7_0_EBX_SMEP (1 << 7) +-#define CPUID_7_0_EBX_BMI2 (1 << 8) +-#define CPUID_7_0_EBX_ERMS (1 << 9) +-#define CPUID_7_0_EBX_INVPCID (1 << 10) +-#define CPUID_7_0_EBX_RTM (1 << 11) +-#define CPUID_7_0_EBX_MPX (1 << 14) +-#define CPUID_7_0_EBX_RDSEED (1 << 18) +-#define CPUID_7_0_EBX_ADX (1 << 19) +-#define CPUID_7_0_EBX_SMAP (1 << 20) ++#define CPUID_EXT3_LAHF_LM (1U << 0) ++#define CPUID_EXT3_CMP_LEG (1U << 1) ++#define CPUID_EXT3_SVM (1U << 2) ++#define CPUID_EXT3_EXTAPIC (1U << 3) ++#define CPUID_EXT3_CR8LEG (1U << 4) ++#define CPUID_EXT3_ABM (1U << 5) ++#define CPUID_EXT3_SSE4A (1U << 6) ++#define CPUID_EXT3_MISALIGNSSE (1U << 7) ++#define CPUID_EXT3_3DNOWPREFETCH (1U << 8) ++#define CPUID_EXT3_OSVW (1U << 9) ++#define CPUID_EXT3_IBS (1U << 10) ++#define CPUID_EXT3_XOP (1U << 11) ++#define CPUID_EXT3_SKINIT (1U << 12) ++#define CPUID_EXT3_WDT (1U << 13) ++#define CPUID_EXT3_LWP (1U << 15) ++#define CPUID_EXT3_FMA4 (1U << 16) ++#define CPUID_EXT3_TCE (1U << 17) ++#define CPUID_EXT3_NODEID (1U << 19) ++#define CPUID_EXT3_TBM (1U << 21) ++#define CPUID_EXT3_TOPOEXT (1U << 22) ++#define CPUID_EXT3_PERFCORE (1U << 23) ++#define CPUID_EXT3_PERFNB (1U << 24) ++ ++#define CPUID_SVM_NPT (1U << 0) ++#define CPUID_SVM_LBRV (1U << 1) ++#define CPUID_SVM_SVMLOCK (1U << 2) ++#define CPUID_SVM_NRIPSAVE (1U << 3) ++#define CPUID_SVM_TSCSCALE (1U << 4) ++#define CPUID_SVM_VMCBCLEAN (1U << 5) ++#define CPUID_SVM_FLUSHASID (1U << 6) ++#define CPUID_SVM_DECODEASSIST (1U << 7) ++#define CPUID_SVM_PAUSEFILTER (1U << 10) ++#define CPUID_SVM_PFTHRESHOLD (1U << 12) ++ ++#define CPUID_7_0_EBX_FSGSBASE (1U << 0) ++#define CPUID_7_0_EBX_BMI1 (1U << 3) ++#define CPUID_7_0_EBX_HLE (1U << 4) ++#define CPUID_7_0_EBX_AVX2 (1U << 5) ++#define CPUID_7_0_EBX_SMEP (1U << 7) ++#define CPUID_7_0_EBX_BMI2 (1U << 8) ++#define CPUID_7_0_EBX_ERMS (1U << 9) ++#define CPUID_7_0_EBX_INVPCID (1U << 10) ++#define CPUID_7_0_EBX_RTM (1U << 11) ++#define CPUID_7_0_EBX_MPX (1U << 14) ++#define CPUID_7_0_EBX_RDSEED (1U << 18) ++#define CPUID_7_0_EBX_ADX (1U << 19) ++#define CPUID_7_0_EBX_SMAP (1U << 20) + + #define CPUID_VENDOR_SZ 12 + +@@ -572,8 +572,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_VENDOR_VIA "CentaurHauls" + +-#define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ +-#define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ ++#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */ ++#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */ + + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Intel-MPX.patch b/SOURCES/kvm-target-i386-Intel-MPX.patch new file mode 100644 index 0000000..a52582d --- /dev/null +++ b/SOURCES/kvm-target-i386-Intel-MPX.patch @@ -0,0 +1,272 @@ +From 0c9168510f4ddbdec3b0a88095db2e8f3f0aeef7 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:23 +0200 +Subject: [PATCH 03/10] target-i386: Intel MPX + +Message-id: <1435260689-9556-3-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66500 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/8] target-i386: Intel MPX +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: Liu Jinsong + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1233350 + +Add some MPX related definiation, and hardcode sizes and offsets +of xsave features 3 and 4. It also add corresponding part to +kvm_get/put_xsave, and vmstate. + +Signed-off-by: Liu Jinsong +Signed-off-by: Paolo Bonzini +(cherry picked from commit 79e9ebebbf2a00c46fcedb6dc7dd5e12bbd30216) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina + +Conflicts: + target-i386/kvm.c + target-i386/machine.c +--- + target-i386/cpu.c | 4 ++++ + target-i386/cpu.h | 25 ++++++++++++++++++++++--- + target-i386/kvm.c | 24 ++++++++++++++++++++++++ + target-i386/machine.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 101 insertions(+), 3 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 0fd100f..a9e80d9 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -224,6 +224,10 @@ typedef struct ExtSaveArea { + static const ExtSaveArea ext_save_areas[] = { + [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, + .offset = 0x240, .size = 0x100 }, ++ [3] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, ++ .offset = 0x3c0, .size = 0x40 }, ++ [4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, ++ .offset = 0x400, .size = 0x10 }, + }; + + const char *get_register_name_32(unsigned int reg) +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index e9edd3d..7ebdbb3 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -383,9 +383,14 @@ + + #define MSR_VM_HSAVE_PA 0xc0010117 + +-#define XSTATE_FP 1 +-#define XSTATE_SSE 2 +-#define XSTATE_YMM 4 ++#define MSR_IA32_BNDCFGS 0x00000d90 ++ ++#define XSTATE_FP (1ULL << 0) ++#define XSTATE_SSE (1ULL << 1) ++#define XSTATE_YMM (1ULL << 2) ++#define XSTATE_BNDREGS (1ULL << 3) ++#define XSTATE_BNDCSR (1ULL << 4) ++ + + /* CPUID feature words */ + typedef enum FeatureWord { +@@ -548,6 +553,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EBX_ERMS (1 << 9) + #define CPUID_7_0_EBX_INVPCID (1 << 10) + #define CPUID_7_0_EBX_RTM (1 << 11) ++#define CPUID_7_0_EBX_MPX (1 << 14) + #define CPUID_7_0_EBX_RDSEED (1 << 18) + #define CPUID_7_0_EBX_ADX (1 << 19) + #define CPUID_7_0_EBX_SMAP (1 << 20) +@@ -698,6 +704,16 @@ typedef union { + uint64_t q; + } MMXReg; + ++typedef struct BNDReg { ++ uint64_t lb; ++ uint64_t ub; ++} BNDReg; ++ ++typedef struct BNDCSReg { ++ uint64_t cfgu; ++ uint64_t sts; ++} BNDCSReg; ++ + #ifdef HOST_WORDS_BIGENDIAN + #define XMM_B(n) _b[15 - (n)] + #define XMM_W(n) _w[7 - (n)] +@@ -918,6 +934,9 @@ typedef struct CPUX86State { + + uint64_t xstate_bv; + XMMReg ymmh_regs[CPU_NB_REGS]; ++ BNDReg bnd_regs[4]; ++ BNDCSReg bndcs_regs; ++ uint64_t msr_bndcfgs; + + uint64_t xcr0; + +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index 97ae345..6d9aa63 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -68,6 +68,7 @@ static bool has_msr_tsc_deadline; + static bool has_msr_async_pf_en; + static bool has_msr_pv_eoi_en; + static bool has_msr_misc_enable; ++static bool has_msr_bndcfgs; + static bool has_msr_kvm_steal_time; + static int lm_capable_kernel; + static bool has_msr_hv_hypercall; +@@ -785,6 +786,10 @@ static int kvm_get_supported_msrs(KVMState *s) + has_msr_misc_enable = true; + continue; + } ++ if (kvm_msr_list->indices[i] == MSR_IA32_BNDCFGS) { ++ has_msr_bndcfgs = true; ++ continue; ++ } + } + } + +@@ -988,6 +993,8 @@ static int kvm_put_fpu(X86CPU *cpu) + #define XSAVE_XMM_SPACE 40 + #define XSAVE_XSTATE_BV 128 + #define XSAVE_YMMH_SPACE 144 ++#define XSAVE_BNDREGS 240 ++#define XSAVE_BNDCSR 256 + + static int kvm_put_xsave(X86CPU *cpu) + { +@@ -1020,6 +1027,10 @@ static int kvm_put_xsave(X86CPU *cpu) + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; + memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, + sizeof env->ymmh_regs); ++ memcpy(&xsave->region[XSAVE_BNDREGS], env->bnd_regs, ++ sizeof env->bnd_regs); ++ memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, ++ sizeof(env->bndcs_regs)); + r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); + return r; + } +@@ -1255,6 +1266,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + MSR_MTRRphysMask(i), env->mtrr_var[i].mask); + } + } ++ if (has_msr_bndcfgs) { ++ kvm_msr_entry_set(&msrs[n++], MSR_IA32_BNDCFGS, env->msr_bndcfgs); ++ } + } + if (env->mcg_cap) { + int i; +@@ -1336,6 +1350,10 @@ static int kvm_get_xsave(X86CPU *cpu) + env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; + memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE], + sizeof env->ymmh_regs); ++ memcpy(env->bnd_regs, &xsave->region[XSAVE_BNDREGS], ++ sizeof env->bnd_regs); ++ memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR], ++ sizeof(env->bndcs_regs)); + return 0; + } + +@@ -1479,6 +1497,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_misc_enable) { + msrs[n++].index = MSR_IA32_MISC_ENABLE; + } ++ if (has_msr_bndcfgs) { ++ msrs[n++].index = MSR_IA32_BNDCFGS; ++ } + + if (!env->tsc_valid) { + msrs[n++].index = MSR_IA32_TSC; +@@ -1620,6 +1641,9 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_IA32_MISC_ENABLE: + env->msr_ia32_misc_enable = msrs[i].data; + break; ++ case MSR_IA32_BNDCFGS: ++ env->msr_bndcfgs = msrs[i].data; ++ break; + default: + if (msrs[i].index >= MSR_MC0_CTL && + msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 4c1ead4..b6be606 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -63,6 +63,21 @@ static const VMStateDescription vmstate_ymmh_reg = { + #define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg) + ++static const VMStateDescription vmstate_bnd_regs = { ++ .name = "bnd_regs", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(lb, BNDReg), ++ VMSTATE_UINT64(ub, BNDReg), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#define VMSTATE_BND_REGS(_field, _state, _n) \ ++ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_bnd_regs, BNDReg) ++ + static const VMStateDescription vmstate_mtrr_var = { + .name = "mtrr_var", + .version_id = 1, +@@ -572,6 +587,39 @@ static const VMStateDescription vmstate_msr_hyperv_time = { + } + }; + ++static bool mpx_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ unsigned int i; ++ ++ for (i = 0; i < 4; i++) { ++ if (env->bnd_regs[i].lb || env->bnd_regs[i].ub) { ++ return true; ++ } ++ } ++ ++ if (env->bndcs_regs.cfgu || env->bndcs_regs.sts) { ++ return true; ++ } ++ ++ return !!env->msr_bndcfgs; ++} ++ ++static const VMStateDescription vmstate_mpx = { ++ .name = "cpu/mpx", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_BND_REGS(env.bnd_regs, X86CPU, 4), ++ VMSTATE_UINT64(env.bndcs_regs.cfgu, X86CPU), ++ VMSTATE_UINT64(env.bndcs_regs.sts, X86CPU), ++ VMSTATE_UINT64(env.msr_bndcfgs, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + const VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -713,6 +761,9 @@ const VMStateDescription vmstate_x86_cpu = { + .vmsd = &vmstate_msr_hyperv_time, + .needed = hyperv_time_enable_needed, + } , { ++ .vmsd = &vmstate_mpx, ++ .needed = mpx_needed, ++ } , { + /* empty */ + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-Intel-AVX-512-support.patch b/SOURCES/kvm-target-i386-add-Intel-AVX-512-support.patch new file mode 100644 index 0000000..dc644dd --- /dev/null +++ b/SOURCES/kvm-target-i386-add-Intel-AVX-512-support.patch @@ -0,0 +1,337 @@ +From 5567938d29bf8a0ce451e59a8db009c12ab3444c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:29 +0200 +Subject: [PATCH 09/10] target-i386: add Intel AVX-512 support + +Message-id: <1435260689-9556-9-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66506 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 8/8] target-i386: add Intel AVX-512 support +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +Add AVX512 feature bits, register definition and corresponding +xsave/vmstate support. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Chao Peng +Signed-off-by: Paolo Bonzini +(cherry picked from commit 9aecd6f8aef653cea58932f06a2740299dbe5fd3) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina + +Conflicts: + target-i386/cpu.h + target-i386/machine.c +--- + target-i386/cpu.c | 10 ++++-- + target-i386/cpu.h | 61 ++++++++++++++++++++++++++++++++++++ + target-i386/kvm.c | 19 +++++++++++ + target-i386/machine.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 175 insertions(+), 2 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index fe60c33..06efe17 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -146,8 +146,8 @@ static const char *svm_feature_name[] = { + static const char *cpuid_7_0_ebx_feature_name[] = { + "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL, +- NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ++ "avx512f", NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, ++ NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL, + }; + + typedef struct FeatureWordInfo { +@@ -228,6 +228,12 @@ static const ExtSaveArea ext_save_areas[] = { + .offset = 0x3c0, .size = 0x40 }, + [4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, + .offset = 0x400, .size = 0x40 }, ++ [5] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, ++ .offset = 0x440, .size = 0x40 }, ++ [6] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, ++ .offset = 0x480, .size = 0x200 }, ++ [7] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, ++ .offset = 0x680, .size = 0x400 }, + }; + + const char *get_register_name_32(unsigned int reg) +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index fc1e42e..61e9b86 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -390,6 +390,9 @@ + #define XSTATE_YMM (1ULL << 2) + #define XSTATE_BNDREGS (1ULL << 3) + #define XSTATE_BNDCSR (1ULL << 4) ++#define XSTATE_OPMASK (1ULL << 5) ++#define XSTATE_ZMM_Hi256 (1ULL << 6) ++#define XSTATE_Hi16_ZMM (1ULL << 7) + + + /* CPUID feature words */ +@@ -554,9 +557,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EBX_INVPCID (1U << 10) + #define CPUID_7_0_EBX_RTM (1U << 11) + #define CPUID_7_0_EBX_MPX (1U << 14) ++#define CPUID_7_0_EBX_AVX512F (1U << 16) /* AVX-512 Foundation */ + #define CPUID_7_0_EBX_RDSEED (1U << 18) + #define CPUID_7_0_EBX_ADX (1U << 19) + #define CPUID_7_0_EBX_SMAP (1U << 20) ++#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */ ++#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */ ++#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */ + + #define CPUID_VENDOR_SZ 12 + +@@ -697,6 +704,24 @@ typedef union { + } XMMReg; + + typedef union { ++ uint8_t _b[32]; ++ uint16_t _w[16]; ++ uint32_t _l[8]; ++ uint64_t _q[4]; ++ float32 _s[8]; ++ float64 _d[4]; ++} YMMReg; ++ ++typedef union { ++ uint8_t _b[64]; ++ uint16_t _w[32]; ++ uint32_t _l[16]; ++ uint64_t _q[8]; ++ float32 _s[16]; ++ float64 _d[8]; ++} ZMMReg; ++ ++typedef union { + uint8_t _b[8]; + uint16_t _w[4]; + uint32_t _l[2]; +@@ -715,6 +740,20 @@ typedef struct BNDCSReg { + } BNDCSReg; + + #ifdef HOST_WORDS_BIGENDIAN ++#define ZMM_B(n) _b[63 - (n)] ++#define ZMM_W(n) _w[31 - (n)] ++#define ZMM_L(n) _l[15 - (n)] ++#define ZMM_S(n) _s[15 - (n)] ++#define ZMM_Q(n) _q[7 - (n)] ++#define ZMM_D(n) _d[7 - (n)] ++ ++#define YMM_B(n) _b[31 - (n)] ++#define YMM_W(n) _w[15 - (n)] ++#define YMM_L(n) _l[7 - (n)] ++#define YMM_S(n) _s[7 - (n)] ++#define YMM_Q(n) _q[3 - (n)] ++#define YMM_D(n) _d[3 - (n)] ++ + #define XMM_B(n) _b[15 - (n)] + #define XMM_W(n) _w[7 - (n)] + #define XMM_L(n) _l[3 - (n)] +@@ -727,6 +766,20 @@ typedef struct BNDCSReg { + #define MMX_L(n) _l[1 - (n)] + #define MMX_S(n) _s[1 - (n)] + #else ++#define ZMM_B(n) _b[n] ++#define ZMM_W(n) _w[n] ++#define ZMM_L(n) _l[n] ++#define ZMM_S(n) _s[n] ++#define ZMM_Q(n) _q[n] ++#define ZMM_D(n) _d[n] ++ ++#define YMM_B(n) _b[n] ++#define YMM_W(n) _w[n] ++#define YMM_L(n) _l[n] ++#define YMM_S(n) _s[n] ++#define YMM_Q(n) _q[n] ++#define YMM_D(n) _d[n] ++ + #define XMM_B(n) _b[n] + #define XMM_W(n) _w[n] + #define XMM_L(n) _l[n] +@@ -765,6 +818,8 @@ typedef struct { + + #define NB_MMU_MODES 3 + ++#define NB_OPMASK_REGS 8 ++ + typedef enum TPRAccess { + TPR_ACCESS_READ, + TPR_ACCESS_WRITE, +@@ -826,6 +881,12 @@ typedef struct CPUX86State { + + XMMReg ymmh_regs[CPU_NB_REGS]; + ++ uint64_t opmask_regs[NB_OPMASK_REGS]; ++ YMMReg zmmh_regs[CPU_NB_REGS]; ++#ifdef TARGET_X86_64 ++ ZMMReg hi16_zmm_regs[CPU_NB_REGS]; ++#endif ++ + /* sysenter registers */ + uint32_t sysenter_cs; + target_ulong sysenter_esp; +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index bbbbac0..c91bfb8 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -995,6 +995,9 @@ static int kvm_put_fpu(X86CPU *cpu) + #define XSAVE_YMMH_SPACE 144 + #define XSAVE_BNDREGS 240 + #define XSAVE_BNDCSR 256 ++#define XSAVE_OPMASK 272 ++#define XSAVE_ZMM_Hi256 288 ++#define XSAVE_Hi16_ZMM 416 + + static int kvm_put_xsave(X86CPU *cpu) + { +@@ -1031,6 +1034,14 @@ static int kvm_put_xsave(X86CPU *cpu) + sizeof env->bnd_regs); + memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, + sizeof(env->bndcs_regs)); ++ memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs, ++ sizeof env->opmask_regs); ++ memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs, ++ sizeof env->zmmh_regs); ++#ifdef TARGET_X86_64 ++ memcpy(&xsave->region[XSAVE_Hi16_ZMM], env->hi16_zmm_regs, ++ sizeof env->hi16_zmm_regs); ++#endif + r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); + return r; + } +@@ -1354,6 +1365,14 @@ static int kvm_get_xsave(X86CPU *cpu) + sizeof env->bnd_regs); + memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR], + sizeof(env->bndcs_regs)); ++ memcpy(env->opmask_regs, &xsave->region[XSAVE_OPMASK], ++ sizeof env->opmask_regs); ++ memcpy(env->zmmh_regs, &xsave->region[XSAVE_ZMM_Hi256], ++ sizeof env->zmmh_regs); ++#ifdef TARGET_X86_64 ++ memcpy(env->hi16_zmm_regs, &xsave->region[XSAVE_Hi16_ZMM], ++ sizeof env->hi16_zmm_regs); ++#endif + return 0; + } + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index b6be606..2c97002 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -63,6 +63,44 @@ static const VMStateDescription vmstate_ymmh_reg = { + #define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg) + ++static const VMStateDescription vmstate_zmmh_reg = { ++ .name = "zmmh_reg", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(YMM_Q(0), YMMReg), ++ VMSTATE_UINT64(YMM_Q(1), YMMReg), ++ VMSTATE_UINT64(YMM_Q(2), YMMReg), ++ VMSTATE_UINT64(YMM_Q(3), YMMReg), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _n) \ ++ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_zmmh_reg, YMMReg) ++ ++#ifdef TARGET_X86_64 ++static const VMStateDescription vmstate_hi16_zmm_reg = { ++ .name = "hi16_zmm_reg", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(ZMM_Q(0), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(1), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(2), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(3), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(4), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(5), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(6), ZMMReg), ++ VMSTATE_UINT64(ZMM_Q(7), ZMMReg), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _n) \ ++ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_hi16_zmm_reg, ZMMReg) ++#endif ++ + static const VMStateDescription vmstate_bnd_regs = { + .name = "bnd_regs", + .version_id = 1, +@@ -620,6 +658,52 @@ static const VMStateDescription vmstate_mpx = { + } + }; + ++static bool avx512_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ unsigned int i; ++ ++ for (i = 0; i < NB_OPMASK_REGS; i++) { ++ if (env->opmask_regs[i]) { ++ return true; ++ } ++ } ++ ++ for (i = 0; i < CPU_NB_REGS; i++) { ++#define ENV_ZMMH(reg, field) (env->zmmh_regs[reg].YMM_Q(field)) ++ if (ENV_ZMMH(i, 0) || ENV_ZMMH(i, 1) || ++ ENV_ZMMH(i, 2) || ENV_ZMMH(i, 3)) { ++ return true; ++ } ++#ifdef TARGET_X86_64 ++#define ENV_Hi16_ZMM(reg, field) (env->hi16_zmm_regs[reg].ZMM_Q(field)) ++ if (ENV_Hi16_ZMM(i, 0) || ENV_Hi16_ZMM(i, 1) || ++ ENV_Hi16_ZMM(i, 2) || ENV_Hi16_ZMM(i, 3) || ++ ENV_Hi16_ZMM(i, 4) || ENV_Hi16_ZMM(i, 5) || ++ ENV_Hi16_ZMM(i, 6) || ENV_Hi16_ZMM(i, 7)) { ++ return true; ++ } ++#endif ++ } ++ ++ return false; ++} ++ ++static const VMStateDescription vmstate_avx512 = { ++ .name = "cpu/avx512", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS), ++ VMSTATE_ZMMH_REGS_VARS(env.zmmh_regs, X86CPU, CPU_NB_REGS), ++#ifdef TARGET_X86_64 ++ VMSTATE_Hi16_ZMM_REGS_VARS(env.hi16_zmm_regs, X86CPU, CPU_NB_REGS), ++#endif ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + const VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -763,6 +847,9 @@ const VMStateDescription vmstate_x86_cpu = { + } , { + .vmsd = &vmstate_mpx, + .needed = mpx_needed, ++ }, { ++ .vmsd = &vmstate_avx512, ++ .needed = avx512_needed, + } , { + /* empty */ + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-bugfix-of-Intel-MPX.patch b/SOURCES/kvm-target-i386-bugfix-of-Intel-MPX.patch new file mode 100644 index 0000000..04dcbd1 --- /dev/null +++ b/SOURCES/kvm-target-i386-bugfix-of-Intel-MPX.patch @@ -0,0 +1,47 @@ +From ec56a547380c2cecda150988545287fafee14a6d Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:25 +0200 +Subject: [PATCH 05/10] target-i386: bugfix of Intel MPX + +Message-id: <1435260689-9556-5-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66502 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 4/8] target-i386: bugfix of Intel MPX +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: "Liu, Jinsong" + +The correct size of cpuid 0x0d sub-leaf 4 is 0x40, not 0x10. +This is confirmed by Anvin H Peter and Mallick Asit K. + +Signed-off-by: Liu Jinsong +Cc: H. Peter Anvin +Cc: Asit K Mallick +Signed-off-by: Paolo Bonzini + +Signed-off-by: Liu, Jinsong +(cherry picked from commit b0f15a5d5628994c71a6f428f360a5a537ad3b39) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index a9e80d9..2eeff5c 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -227,7 +227,7 @@ static const ExtSaveArea ext_save_areas[] = { + [3] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, + .offset = 0x3c0, .size = 0x40 }, + [4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, +- .offset = 0x400, .size = 0x10 }, ++ .offset = 0x400, .size = 0x40 }, + }; + + const char *get_register_name_32(unsigned int reg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-fix-cpuid-leaf-0x0d.patch b/SOURCES/kvm-target-i386-fix-cpuid-leaf-0x0d.patch new file mode 100644 index 0000000..4318112 --- /dev/null +++ b/SOURCES/kvm-target-i386-fix-cpuid-leaf-0x0d.patch @@ -0,0 +1,59 @@ +From 39ffb75b89ae1a1be6e6ed5c03d4c22cc640e832 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:22 +0200 +Subject: [PATCH 02/10] target-i386: fix cpuid leaf 0x0d + +Message-id: <1435260689-9556-2-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66499 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/8] target-i386: fix cpuid leaf 0x0d +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: Liu Jinsong + +Fix cpuid leaf 0x0d which incorrectly parsed eax and ebx. + +However, before this patch the CPUID worked fine -- the .offset +field contained the size _and_ was stored in the register that +is supposed to hold the size (eax), and likewise the .size field +contained the offset _and_ was stored in the register trhat is +supposed to hold the offset (ebx). + +Signed-off-by: Liu Jinsong +Signed-off-by: Paolo Bonzini +(cherry picked from commit 33f373d7c56350fd2ec3e31f4f2c46cb49464911) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index b76719d..0fd100f 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -223,7 +223,7 @@ typedef struct ExtSaveArea { + + static const ExtSaveArea ext_save_areas[] = { + [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, +- .offset = 0x100, .size = 0x240 }, ++ .offset = 0x240, .size = 0x100 }, + }; + + const char *get_register_name_32(unsigned int reg) +@@ -2191,8 +2191,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + const ExtSaveArea *esa = &ext_save_areas[count]; + if ((env->features[esa->feature] & esa->bits) == esa->bits && + (kvm_mask & (1 << count)) != 0) { +- *eax = esa->offset; +- *ebx = esa->size; ++ *eax = esa->size; ++ *ebx = esa->offset; + } + } + break; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-fix-set-of-registers-zeroed-on-reset.patch b/SOURCES/kvm-target-i386-fix-set-of-registers-zeroed-on-reset.patch new file mode 100644 index 0000000..acdfe67 --- /dev/null +++ b/SOURCES/kvm-target-i386-fix-set-of-registers-zeroed-on-reset.patch @@ -0,0 +1,94 @@ +From 5f40ed9dd62b914f259c1b6a51298fedb6bb2a24 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 25 Jun 2015 19:31:26 +0200 +Subject: [PATCH 06/10] target-i386: fix set of registers zeroed on reset + +Message-id: <1435260689-9556-6-git-send-email-ehabkost@redhat.com> +Patchwork-id: 66505 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 5/8] target-i386: fix set of registers zeroed on reset +Bugzilla: 1233350 +RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini + +From: Paolo Bonzini + +BND0-3, BNDCFGU, BNDCFGS, BNDSTATUS were not zeroed on reset, but they +should be (Intel Instruction Set Extensions Programming Reference +319433-015, pages 9-4 and 9-6). Same for YMM. + +XCR0 should be reset to 1. + +TSC and TSC_RESET were zeroed already by the memset, remove the explicit +assignments. + +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Paolo Bonzini +(cherry picked from commit 05e7e819d7d159a75a46354aead95e1199b8f168) +Signed-off-by: Eduardo Habkost +Signed-off-by: Miroslav Rezanina + +Conflicts: + target-i386/cpu.c + +Backport notes: + * The TSC and TSC_RESET reset lines were never added to the + qemu-kvm-1.5.3 tree +--- + target-i386/cpu.c | 2 ++ + target-i386/cpu.h | 11 ++++++----- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 2eeff5c..96af1bf 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -2402,6 +2402,8 @@ static void x86_cpu_reset(CPUState *s) + cpu_breakpoint_remove_all(env, BP_CPU); + cpu_watchpoint_remove_all(env, BP_CPU); + ++ env->xcr0 = 1; ++ + /* + * SDM 11.11.5 requires: + * - IA32_MTRR_DEF_TYPE MSR.E = 0 +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 7ebdbb3..715ba63 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -798,6 +798,10 @@ typedef struct CPUX86State { + target_ulong cr[5]; /* NOTE: cr1 is unused */ + int32_t a20_mask; + ++ BNDReg bnd_regs[4]; ++ BNDCSReg bndcs_regs; ++ uint64_t msr_bndcfgs; ++ + /* FPU state */ + unsigned int fpstt; /* top of stack index */ + uint16_t fpus; +@@ -820,6 +824,8 @@ typedef struct CPUX86State { + XMMReg xmm_t0; + MMXReg mmx_t0; + ++ XMMReg ymmh_regs[CPU_NB_REGS]; ++ + /* sysenter registers */ + uint32_t sysenter_cs; + target_ulong sysenter_esp; +@@ -931,12 +937,7 @@ typedef struct CPUX86State { + uint16_t fpus_vmstate; + uint16_t fptag_vmstate; + uint16_t fpregs_format_vmstate; +- + uint64_t xstate_bv; +- XMMReg ymmh_regs[CPU_NB_REGS]; +- BNDReg bnd_regs[4]; +- BNDCSReg bndcs_regs; +- uint64_t msr_bndcfgs; + + uint64_t xcr0; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-trace-add-qemu_system_powerdown_request-and-qemu_sys.patch b/SOURCES/kvm-trace-add-qemu_system_powerdown_request-and-qemu_sys.patch new file mode 100644 index 0000000..cace807 --- /dev/null +++ b/SOURCES/kvm-trace-add-qemu_system_powerdown_request-and-qemu_sys.patch @@ -0,0 +1,110 @@ +From 5e18df4d60ba22586ec4f4d80804ee8d4e41372e Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 23 Oct 2014 10:03:09 +0200 +Subject: [PATCH 01/16] trace: add qemu_system_powerdown_request and + qemu_system_shutdown_request trace events + +Message-id: <1414058589-12881-1-git-send-email-stefanha@redhat.com> +Patchwork-id: 61833 +O-Subject: [RHEL7.2 qemu-kvm PATCH] trace: add qemu_system_powerdown_request and qemu_system_shutdown_request trace events +Bugzilla: 1155671 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Amos Kong +RH-Acked-by: Markus Armbruster + +From: Yang Zhiyong + +Bugzilla: 1155671 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=8153235 +Upstream: merged + +We have the experience that the guest doesn't stop successfully +though it was instructed to shut down. + +The root cause may be not in QEMU mostly. However, QEMU is often +suspected at the beginning just because the issue occurred in +virtualization environment. + +Therefore, we need to affirm that QEMU received the shutdown +request and raised ACPI irq from "virsh shutdown" command, +virt-manger or stopping QEMU process to the VM . +So that we can affirm the problems was belonged to the Guset OS +rather than the QEMU itself. + +When we stop guests by "virsh shutdown" command or virt-manger, +or stopping QEMU process, qemu_system_powerdown_request() or +qemu_system_shutdown_request() is called. Then the below functions +in main_loop_should_exit() of Vl.c are called roughly in the +following order. + + if (qemu_powerdown_requested()) + qemu_system_powerdown() + monitor_protocol_event(QEVENT_POWERDOWN, NULL) + + OR + + if(qemu_shutdown_requested()} + monitor_protocol_event(QEVENT_SHUTDOWN, NULL); + +The tracepoint of monitor_protocol_event() already exists, but no +tracepoints are defined for qemu_system_powerdown_request() and +qemu_system_shutdown_request(). So this patch adds two tracepoints for +the two functions. We believe that it will become much easier to +isolate the problem mentioned above by these tracepoints. + +Signed-off-by: Yang Zhiyong +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit bc78cff9757782501db15d39828e6af4186fe331) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Miroslav Rezanina + +Conflicts: + trace-events + +Context conflict, easy to resolve. +--- + trace-events | 2 ++ + vl.c | 2 ++ + 2 files changed, 4 insertions(+) +--- + trace-events | 2 ++ + vl.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/trace-events b/trace-events +index e7bb7e0..b43132c 100644 +--- a/trace-events ++++ b/trace-events +@@ -477,6 +477,8 @@ runstate_set(int new_state) "new state %d" + g_malloc(size_t size, void *ptr) "size %zu ptr %p" + g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" + g_free(void *ptr) "ptr %p" ++qemu_system_shutdown_request(void) "" ++qemu_system_powerdown_request(void) "" + + # block/qcow2.c + qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d" +diff --git a/vl.c b/vl.c +index 2932d7c..2b3dc88 100644 +--- a/vl.c ++++ b/vl.c +@@ -1894,6 +1894,7 @@ void qemu_system_killed(int signal, pid_t pid) + + void qemu_system_shutdown_request(void) + { ++ trace_qemu_system_shutdown_request(); + shutdown_requested = 1; + qemu_notify_event(); + } +@@ -1906,6 +1907,7 @@ static void qemu_system_powerdown(void) + + void qemu_system_powerdown_request(void) + { ++ trace_qemu_system_powerdown_request(); + powerdown_requested = 1; + qemu_notify_event(); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-ccid-add-missing-wakeup-calls.patch b/SOURCES/kvm-usb-ccid-add-missing-wakeup-calls.patch new file mode 100644 index 0000000..b8b301c --- /dev/null +++ b/SOURCES/kvm-usb-ccid-add-missing-wakeup-calls.patch @@ -0,0 +1,76 @@ +From deb3ccfc4df641110546b2af49e885101565143d Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Fri, 17 Jul 2015 11:55:40 +0200 +Subject: [PATCH 01/13] usb-ccid: add missing wakeup calls + +Message-id: <1437134140-27898-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 67056 +O-Subject: [RHEL-7.2 qemu-kvm PATCH v2 1/1] usb-ccid: add missing wakeup calls +Bugzilla: 1243731 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Juan Quintela +RH-Acked-by: Dr. David Alan Gilbert + +Properly notify the host adapter that we have +data pending, so it doesn't has to poll us. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 86d7e214c224f939c897cfa3b6d597f7af4b5bba) +Signed-off-by: Miroslav Rezanina + +Conflicts: + hw/usb/dev-smartcard-reader.c [ slightly different context ] +--- + hw/usb/dev-smartcard-reader.c | 5 +++++ + 1 file changed, 5 insertions(+) +--- + hw/usb/dev-smartcard-reader.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index c1acf70..0e666e1 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -284,6 +284,7 @@ typedef struct CCIDBus { + typedef struct USBCCIDState { + USBDevice dev; + USBEndpoint *intr; ++ USBEndpoint *bulk; + CCIDBus bus; + CCIDCardState *card; + BulkIn bulk_in_pending[BULK_IN_PENDING_NUM]; /* circular */ +@@ -769,6 +770,7 @@ static void ccid_write_slot_status(USBCCIDState *s, CCID_Header *recv) + h->b.bError = s->bError; + h->bClockStatus = CLOCK_STATUS_RUNNING; + ccid_reset_error_status(s); ++ usb_wakeup(s->bulk, 0); + } + + static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv) +@@ -789,6 +791,7 @@ static void ccid_write_parameters(USBCCIDState *s, CCID_Header *recv) + h->bProtocolNum = s->bProtocolNum; + h->abProtocolDataStructure = s->abProtocolDataStructure; + ccid_reset_error_status(s); ++ usb_wakeup(s->bulk, 0); + } + + static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq, +@@ -810,6 +813,7 @@ static void ccid_write_data_block(USBCCIDState *s, uint8_t slot, uint8_t seq, + } + memcpy(p->abData, data, len); + ccid_reset_error_status(s); ++ usb_wakeup(s->bulk, 0); + } + + static void ccid_report_error_failed(USBCCIDState *s, uint8_t error) +@@ -1311,6 +1315,7 @@ static int ccid_initfn(USBDevice *dev) + usb_desc_init(dev); + qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL); + s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); ++ s->bulk = usb_ep_get(dev, USB_TOKEN_IN, CCID_BULK_IN_EP); + s->bus.qbus.allow_hotplug = 1; + s->card = NULL; + s->migration_state = MIGRATION_NONE; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-Drop-superfluous-conditionals-around-g_free.patch b/SOURCES/kvm-util-Drop-superfluous-conditionals-around-g_free.patch new file mode 100644 index 0000000..47cfd5c --- /dev/null +++ b/SOURCES/kvm-util-Drop-superfluous-conditionals-around-g_free.patch @@ -0,0 +1,177 @@ +From 7c92e003601bf83d662f5e21a4bc095de875e906 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:20 +0200 +Subject: [PATCH 2/7] util: Drop superfluous conditionals around g_free() + +Message-id: <1441735585-23432-3-git-send-email-armbru@redhat.com> +Patchwork-id: 67707 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/7] util: Drop superfluous conditionals around g_free() +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Fam Zheng +Signed-off-by: Michael Tokarev +(cherry picked from commit 44c2286b5df1f50fc9fedabd7b1a5a8022e583fc) +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 48 ++++++++++++++++++++++-------------------------- + 1 file changed, 22 insertions(+), 26 deletions(-) + +diff --git a/util/uri.c b/util/uri.c +index bbf2832..01dc09e 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -225,7 +225,7 @@ rfc3986_parse_scheme(URI *uri, const char **str) { + while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || + (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; + if (uri != NULL) { +- if (uri->scheme != NULL) g_free(uri->scheme); ++ g_free(uri->scheme); + uri->scheme = g_strndup(*str, cur - *str); + } + *str = cur; +@@ -262,8 +262,7 @@ rfc3986_parse_fragment(URI *uri, const char **str) + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { +- if (uri->fragment != NULL) +- g_free(uri->fragment); ++ g_free(uri->fragment); + if (uri->cleanup & 2) + uri->fragment = g_strndup(*str, cur - *str); + else +@@ -298,8 +297,7 @@ rfc3986_parse_query(URI *uri, const char **str) + ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) + NEXT(cur); + if (uri != NULL) { +- if (uri->query != NULL) +- g_free (uri->query); ++ g_free(uri->query); + uri->query = g_strndup (*str, cur - *str); + } + *str = cur; +@@ -360,7 +358,7 @@ rfc3986_parse_user_info(URI *uri, const char **str) + NEXT(cur); + if (*cur == '@') { + if (uri != NULL) { +- if (uri->user != NULL) g_free(uri->user); ++ g_free(uri->user); + if (uri->cleanup & 2) + uri->user = g_strndup(*str, cur - *str); + else +@@ -473,9 +471,9 @@ not_ipv4: + NEXT(cur); + found: + if (uri != NULL) { +- if (uri->authority != NULL) g_free(uri->authority); ++ g_free(uri->authority); + uri->authority = NULL; +- if (uri->server != NULL) g_free(uri->server); ++ g_free(uri->server); + if (cur != host) { + if (uri->cleanup & 2) + uri->server = g_strndup(host, cur - host); +@@ -585,7 +583,7 @@ rfc3986_parse_path_ab_empty(URI *uri, const char **str) + if (ret != 0) return(ret); + } + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + if (*str != cur) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); +@@ -631,7 +629,7 @@ rfc3986_parse_path_absolute(URI *uri, const char **str) + } + } + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); +@@ -673,7 +671,7 @@ rfc3986_parse_path_rootless(URI *uri, const char **str) + if (ret != 0) return(ret); + } + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); +@@ -715,7 +713,7 @@ rfc3986_parse_path_no_scheme(URI *uri, const char **str) + if (ret != 0) return(ret); + } + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + if (cur != *str) { + if (uri->cleanup & 2) + uri->path = g_strndup(*str, cur - *str); +@@ -769,7 +767,7 @@ rfc3986_parse_hier_part(URI *uri, const char **str) + } else { + /* path-empty is effectively empty */ + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + uri->path = NULL; + } + } +@@ -812,7 +810,7 @@ rfc3986_parse_relative_ref(URI *uri, const char *str) { + } else { + /* path-empty is effectively empty */ + if (uri != NULL) { +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + uri->path = NULL; + } + } +@@ -1285,21 +1283,21 @@ static void + uri_clean(URI *uri) { + if (uri == NULL) return; + +- if (uri->scheme != NULL) g_free(uri->scheme); ++ g_free(uri->scheme); + uri->scheme = NULL; +- if (uri->server != NULL) g_free(uri->server); ++ g_free(uri->server); + uri->server = NULL; +- if (uri->user != NULL) g_free(uri->user); ++ g_free(uri->user); + uri->user = NULL; +- if (uri->path != NULL) g_free(uri->path); ++ g_free(uri->path); + uri->path = NULL; +- if (uri->fragment != NULL) g_free(uri->fragment); ++ g_free(uri->fragment); + uri->fragment = NULL; +- if (uri->opaque != NULL) g_free(uri->opaque); ++ g_free(uri->opaque); + uri->opaque = NULL; +- if (uri->authority != NULL) g_free(uri->authority); ++ g_free(uri->authority); + uri->authority = NULL; +- if (uri->query != NULL) g_free(uri->query); ++ g_free(uri->query); + uri->query = NULL; + } + +@@ -1711,10 +1709,8 @@ uri_resolve(const char *uri, const char *base) { + /* + * the base fragment must be ignored + */ +- if (bas->fragment != NULL) { +- g_free(bas->fragment); +- bas->fragment = NULL; +- } ++ g_free(bas->fragment); ++ bas->fragment = NULL; + val = uri_to_string(bas); + goto done; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-Fuse-g_malloc-memset-into-g_new0.patch b/SOURCES/kvm-util-Fuse-g_malloc-memset-into-g_new0.patch new file mode 100644 index 0000000..b2bd7cf --- /dev/null +++ b/SOURCES/kvm-util-Fuse-g_malloc-memset-into-g_new0.patch @@ -0,0 +1,40 @@ +From 26622e239160e7dc9811c944d7567f0d8fbb0040 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:21 +0200 +Subject: [PATCH 3/7] util: Fuse g_malloc(); memset() into g_new0() + +Message-id: <1441735585-23432-4-git-send-email-armbru@redhat.com> +Patchwork-id: 67704 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 3/7] util: Fuse g_malloc(); memset() into g_new0() +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Reviewed-by: Fam Zheng +Signed-off-by: Michael Tokarev +(cherry picked from commit 9be71be5bda27b068176ab9b982cf3d7d41a4acd) +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/util/uri.c b/util/uri.c +index 01dc09e..918d235 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -1004,8 +1004,7 @@ URI * + uri_new(void) { + URI *ret; + +- ret = (URI *) g_malloc(sizeof(URI)); +- memset(ret, 0, sizeof(URI)); ++ ret = g_new0(URI, 1); + return(ret); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch b/SOURCES/kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch new file mode 100644 index 0000000..2314d12 --- /dev/null +++ b/SOURCES/kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch @@ -0,0 +1,68 @@ +From 8880d01298ccf89558b95b948984647959d862ae Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:25 +0200 +Subject: [PATCH 7/7] util/uri: Add overflow check to rfc3986_parse_port + +Message-id: <1441735585-23432-8-git-send-email-armbru@redhat.com> +Patchwork-id: 67705 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 7/7] util/uri: Add overflow check to rfc3986_parse_port +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +From: Max Reitz + +And while at it, replace tabs by eight spaces in this function. + +Signed-off-by: Max Reitz +Message-Id: <1424887718-10800-2-git-send-email-mreitz@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2b21233061696feed434317a70e0a8b74f956ec8) +Signed-off-by: Markus Armbruster +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/util/uri.c b/util/uri.c +index 1cfd78b..550b984 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -320,19 +320,23 @@ static int + rfc3986_parse_port(URI *uri, const char **str) + { + const char *cur = *str; ++ int port = 0; + + if (ISA_DIGIT(cur)) { +- if (uri != NULL) +- uri->port = 0; +- while (ISA_DIGIT(cur)) { +- if (uri != NULL) +- uri->port = uri->port * 10 + (*cur - '0'); +- cur++; +- } +- *str = cur; +- return(0); ++ while (ISA_DIGIT(cur)) { ++ port = port * 10 + (*cur - '0'); ++ if (port > 65535) { ++ return 1; ++ } ++ cur++; ++ } ++ if (uri) { ++ uri->port = port; ++ } ++ *str = cur; ++ return 0; + } +- return(1); ++ return 1; + } + + /** +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-uri-URI-member-path-can-be-null-compare-more-ca.patch b/SOURCES/kvm-util-uri-URI-member-path-can-be-null-compare-more-ca.patch new file mode 100644 index 0000000..eb44071 --- /dev/null +++ b/SOURCES/kvm-util-uri-URI-member-path-can-be-null-compare-more-ca.patch @@ -0,0 +1,64 @@ +From 81278fd6c82c8a1c22c65f1ae1ea048d2473dbfe Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:24 +0200 +Subject: [PATCH 6/7] util/uri: URI member path can be null, compare more + carfully + +Message-id: <1441735585-23432-7-git-send-email-armbru@redhat.com> +Patchwork-id: 67709 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 6/7] util/uri: URI member path can be null, compare more carfully +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +uri_resolve_relative() calls strcmp(bas->path, ref->path). However, +either argument could be null! Evidence: the code checks for null +after the comparison. Spotted by Coverity. + +I suspect this was screwed up when we stole the code from libxml2. +There the conditional reads + + xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path) + +with + + int + xmlStrEqual(const xmlChar *str1, const xmlChar *str2) { + if (str1 == str2) return(1); + if (str1 == NULL) return(0); + if (str2 == NULL) return(0); + do { + if (*str1++ != *str2) return(0); + } while (*str2++); + return(1); + } + +Fix by replicating libxml2's logic faithfully. + +Cc: Paolo Bonzini +Signed-off-by: Markus Armbruster +Signed-off-by: Michael Tokarev +(cherry picked from commit afb30dde3ad71349fc65726946d58e5d3c61f8af) +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util/uri.c b/util/uri.c +index b9a7b54..1cfd78b 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -1935,7 +1935,8 @@ uri_resolve_relative (const char *uri, const char * base) + val = g_strdup (uri); + goto done; + } +- if (!strcmp(bas->path, ref->path)) { ++ if (bas->path == ref->path || ++ (bas->path && ref->path && !strcmp(bas->path, ref->path))) { + val = g_strdup(""); + goto done; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-uri-realloc2n-can-t-fail-drop-dead-error-handli.patch b/SOURCES/kvm-util-uri-realloc2n-can-t-fail-drop-dead-error-handli.patch new file mode 100644 index 0000000..b1317f8 --- /dev/null +++ b/SOURCES/kvm-util-uri-realloc2n-can-t-fail-drop-dead-error-handli.patch @@ -0,0 +1,180 @@ +From 3704c5a2d54b2e4e492ce7dc8606fe1dc4a2c547 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:23 +0200 +Subject: [PATCH 5/7] util/uri: realloc2n() can't fail, drop dead error + handling + +Message-id: <1441735585-23432-6-git-send-email-armbru@redhat.com> +Patchwork-id: 67710 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 5/7] util/uri: realloc2n() can't fail, drop dead error handling +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +Signed-off-by: Markus Armbruster +Signed-off-by: Michael Tokarev +(cherry picked from commit afd5ea3671f936f511015a71af9cd0ed23788515) +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/util/uri.c b/util/uri.c +index aa39694..b9a7b54 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -1049,14 +1049,12 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; + } + if (len >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = ':'; +@@ -1066,7 +1064,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) +@@ -1083,7 +1080,6 @@ uri_to_string(URI *uri) { + if (uri->server != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; +@@ -1093,7 +1089,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || +@@ -1112,7 +1107,6 @@ uri_to_string(URI *uri) { + } + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '@'; +@@ -1121,7 +1115,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; +@@ -1129,7 +1122,6 @@ uri_to_string(URI *uri) { + if (uri->port > 0) { + if (len + 10 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + len += snprintf(&ret[len], max - len, ":%d", uri->port); +@@ -1137,7 +1129,6 @@ uri_to_string(URI *uri) { + } else if (uri->authority != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; +@@ -1146,7 +1137,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || +@@ -1165,7 +1155,6 @@ uri_to_string(URI *uri) { + } else if (uri->scheme != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '/'; +@@ -1185,7 +1174,6 @@ uri_to_string(URI *uri) { + (!strcmp(uri->scheme, "file"))) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; +@@ -1195,7 +1183,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || +@@ -1215,7 +1202,6 @@ uri_to_string(URI *uri) { + if (uri->query != NULL) { + if (len + 1 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '?'; +@@ -1223,7 +1209,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 1 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = *p++; +@@ -1233,7 +1218,6 @@ uri_to_string(URI *uri) { + if (uri->fragment != NULL) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len++] = '#'; +@@ -1241,7 +1225,6 @@ uri_to_string(URI *uri) { + while (*p != 0) { + if (len + 3 >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) +@@ -1257,15 +1240,10 @@ uri_to_string(URI *uri) { + } + if (len >= max) { + temp = realloc2n(ret, &max); +- if (temp == NULL) goto mem_error; + ret = temp; + } + ret[len] = 0; + return(ret); +- +-mem_error: +- g_free(ret); +- return(NULL); + } + + /** +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-uri-uri_new-can-t-fail-drop-dead-error-handling.patch b/SOURCES/kvm-util-uri-uri_new-can-t-fail-drop-dead-error-handling.patch new file mode 100644 index 0000000..ca780f8 --- /dev/null +++ b/SOURCES/kvm-util-uri-uri_new-can-t-fail-drop-dead-error-handling.patch @@ -0,0 +1,113 @@ +From 9a2e25a1a72443b00a54fb1660c818856c2569c6 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 8 Sep 2015 18:06:22 +0200 +Subject: [PATCH 4/7] util/uri: uri_new() can't fail, drop dead error handling + +Message-id: <1441735585-23432-5-git-send-email-armbru@redhat.com> +Patchwork-id: 67703 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 4/7] util/uri: uri_new() can't fail, drop dead error handling +Bugzilla: 1218919 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Dr. David Alan Gilbert + +Signed-off-by: Markus Armbruster +Signed-off-by: Michael Tokarev +(cherry picked from commit c89c6e80a66aac16d7b14ff21e0aaeb99ebfe165) +Signed-off-by: Miroslav Rezanina +--- + util/uri.c | 36 +++++++++++------------------------- + 1 file changed, 11 insertions(+), 25 deletions(-) + +diff --git a/util/uri.c b/util/uri.c +index 918d235..aa39694 100644 +--- a/util/uri.c ++++ b/util/uri.c +@@ -928,12 +928,10 @@ uri_parse(const char *str) { + if (str == NULL) + return(NULL); + uri = uri_new(); +- if (uri != NULL) { +- ret = rfc3986_parse_uri_reference(uri, str); +- if (ret) { +- uri_free(uri); +- return(NULL); +- } ++ ret = rfc3986_parse_uri_reference(uri, str); ++ if (ret) { ++ uri_free(uri); ++ return(NULL); + } + return(uri); + } +@@ -974,15 +972,13 @@ uri_parse_raw(const char *str, int raw) { + if (str == NULL) + return(NULL); + uri = uri_new(); +- if (uri != NULL) { +- if (raw) { +- uri->cleanup |= 2; +- } +- ret = uri_parse_into(uri, str); +- if (ret) { +- uri_free(uri); +- return(NULL); +- } ++ if (raw) { ++ uri->cleanup |= 2; ++ } ++ ret = uri_parse_into(uri, str); ++ if (ret) { ++ uri_free(uri); ++ return(NULL); + } + return(uri); + } +@@ -1675,8 +1671,6 @@ uri_resolve(const char *uri, const char *base) { + else { + if (*uri) { + ref = uri_new(); +- if (ref == NULL) +- goto done; + ret = uri_parse_into(ref, uri); + } + else +@@ -1695,8 +1689,6 @@ uri_resolve(const char *uri, const char *base) { + ret = -1; + else { + bas = uri_new(); +- if (bas == NULL) +- goto done; + ret = uri_parse_into(bas, base); + } + if (ret != 0) { +@@ -1727,8 +1719,6 @@ uri_resolve(const char *uri, const char *base) { + * document. + */ + res = uri_new(); +- if (res == NULL) +- goto done; + if ((ref->scheme == NULL) && (ref->path == NULL) && + ((ref->authority == NULL) && (ref->server == NULL))) { + res->scheme = g_strdup(bas->scheme); +@@ -1933,8 +1923,6 @@ uri_resolve_relative (const char *uri, const char * base) + * First parse URI into a standard form + */ + ref = uri_new (); +- if (ref == NULL) +- return NULL; + /* If URI not already in "relative" form */ + if (uri[0] != '.') { + ret = uri_parse_into (ref, uri); +@@ -1951,8 +1939,6 @@ uri_resolve_relative (const char *uri, const char * base) + goto done; + } + bas = uri_new (); +- if (bas == NULL) +- goto done; + if (base[0] != '.') { + ret = uri_parse_into (bas, base); + if (ret != 0) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-Correction-in-vfio_rom_read-when-attempting-rom.patch b/SOURCES/kvm-vfio-Correction-in-vfio_rom_read-when-attempting-rom.patch new file mode 100644 index 0000000..0954434 --- /dev/null +++ b/SOURCES/kvm-vfio-Correction-in-vfio_rom_read-when-attempting-rom.patch @@ -0,0 +1,50 @@ +From d6d48e0a9ce4dfc91085e450f2a9a334b1ece89b Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:33:51 +0200 +Subject: [PATCH 03/14] vfio: Correction in vfio_rom_read when attempting rom + loading + +Message-id: <20150410163351.15324.30965.stgit@gimli.home> +Patchwork-id: 64785 +O-Subject: [RHEL7.2 qemu-kvm PATCH 3/8] vfio: Correction in vfio_rom_read when attempting rom loading +Bugzilla: 1210503 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +From: Bandan Das + +Upstream: db01eedb6d883a1fed5b4079f8a6ff048b9c1217 + +commit e638073c569e801ce9de added a flag to track whether +a previous rom read had failed. Accidentally, the code +ended up adding vfio_load_option_rom twice. (Thanks to Alex +for spotting it) + +Signed-off-by: Bandan Das +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index f3bf491..57bc974 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -1235,11 +1235,8 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size) + uint64_t val = ((uint64_t)1 << (size * 8)) - 1; + + /* Load the ROM lazily when the guest tries to read it */ +- if (unlikely(!vdev->rom)) { ++ if (unlikely(!vdev->rom && !vdev->rom_read_failed)) { + vfio_pci_load_rom(vdev); +- if (unlikely(!vdev->rom && !vdev->rom_read_failed)) { +- vfio_pci_load_rom(vdev); +- } + } + + memcpy(&val, vdev->rom + addr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-Do-not-reattempt-a-failed-rom-read.patch b/SOURCES/kvm-vfio-Do-not-reattempt-a-failed-rom-read.patch new file mode 100644 index 0000000..09f3fbf --- /dev/null +++ b/SOURCES/kvm-vfio-Do-not-reattempt-a-failed-rom-read.patch @@ -0,0 +1,72 @@ +From d8cc073c06a4c79e24a86a958b8c1ac7a26fa039 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:33:45 +0200 +Subject: [PATCH 02/14] vfio: Do not reattempt a failed rom read + +Message-id: <20150410163345.15324.23733.stgit@gimli.home> +Patchwork-id: 64790 +O-Subject: [RHEL7.2 qemu-kvm PATCH 2/8] vfio: Do not reattempt a failed rom read +Bugzilla: 1210503 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +From: Bandan Das + +Upstream: e638073c569e801ce9def2016a84f955cbbca779 + +During lazy rom loading, if rom read fails, and the +guest attempts a read again, vfio will again attempt it. +Add a boolean to prevent this. There could be a case where +a failed rom read might succeed the next time because of +a device reset or such, but it's best to exclude unpredictable +behavior + +Signed-off-by: Bandan Das +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index c9dbc28..f3bf491 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -206,6 +206,7 @@ typedef struct VFIODevice { + bool has_flr; + bool has_pm_reset; + bool needs_reset; ++ bool rom_read_failed; + } VFIODevice; + + typedef struct VFIOGroup { +@@ -1197,6 +1198,7 @@ static void vfio_pci_load_rom(VFIODevice *vdev) + vdev->rom_offset = reg_info.offset; + + if (!vdev->rom_size) { ++ vdev->rom_read_failed = true; + error_report("vfio-pci: Cannot read device rom at " + "%04x:%02x:%02x.%x\n", + vdev->host.domain, vdev->host.bus, vdev->host.slot, +@@ -1235,6 +1237,9 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size) + /* Load the ROM lazily when the guest tries to read it */ + if (unlikely(!vdev->rom)) { + vfio_pci_load_rom(vdev); ++ if (unlikely(!vdev->rom && !vdev->rom_read_failed)) { ++ vfio_pci_load_rom(vdev); ++ } + } + + memcpy(&val, vdev->rom + addr, +@@ -1352,6 +1357,7 @@ static void vfio_pci_size_rom(VFIODevice *vdev) + PCI_BASE_ADDRESS_SPACE_MEMORY, &vdev->pdev.rom); + + vdev->pdev.has_rom = true; ++ vdev->rom_read_failed = false; + } + + static void vfio_vga_write(void *opaque, hwaddr addr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-Fix-overrun-after-readlink-fills-buffer-complet.patch b/SOURCES/kvm-vfio-Fix-overrun-after-readlink-fills-buffer-complet.patch new file mode 100644 index 0000000..c11cc27 --- /dev/null +++ b/SOURCES/kvm-vfio-Fix-overrun-after-readlink-fills-buffer-complet.patch @@ -0,0 +1,55 @@ +From a254fe579062a9eaf97f2b81474c19b4b46ddc85 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:33:56 +0200 +Subject: [PATCH 04/14] vfio: Fix overrun after readlink() fills buffer + completely + +Message-id: <20150410163356.15324.47617.stgit@gimli.home> +Patchwork-id: 64786 +O-Subject: [RHEL7.2 qemu-kvm PATCH 4/8] vfio: Fix overrun after readlink() fills buffer completely +Bugzilla: 1210504 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +From: Markus Armbruster + +Upstream: 13665a2d2f675341e73618fcd7f9d36b6c68b509 + +readlink() returns the number of bytes written to the buffer, and it +doesn't write a terminating null byte. vfio_init() writes it itself. +Overruns the buffer when readlink() filled it completely. + +Fix by treating readlink() filling the buffer completely as error, +like we do in pci-assign.c's assign_failed_examine(). + +Spotted by Coverity. + +Signed-off-by: Markus Armbruster +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 57bc974..81e6594 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3767,10 +3767,10 @@ static int vfio_initfn(PCIDevice *pdev) + + strncat(path, "iommu_group", sizeof(path) - strlen(path) - 1); + +- len = readlink(path, iommu_group_path, PATH_MAX); +- if (len <= 0) { ++ len = readlink(path, iommu_group_path, sizeof(path)); ++ if (len <= 0 || len >= sizeof(path)) { + error_report("vfio: error no iommu_group for device"); +- return -errno; ++ return len < 0 ? -errno : ENAMETOOLONG; + } + + iommu_group_path[len] = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-Use-vfio-type1-v2-IOMMU-interface.patch b/SOURCES/kvm-vfio-Use-vfio-type1-v2-IOMMU-interface.patch new file mode 100644 index 0000000..b4315e6 --- /dev/null +++ b/SOURCES/kvm-vfio-Use-vfio-type1-v2-IOMMU-interface.patch @@ -0,0 +1,73 @@ +From d9bcfe28139d190ed9847217dd309296580c2b7e Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:34:13 +0200 +Subject: [PATCH 07/14] vfio: Use vfio type1 v2 IOMMU interface + +Message-id: <20150410163413.15324.90697.stgit@gimli.home> +Patchwork-id: 64787 +O-Subject: [RHEL7.2 qemu-kvm PATCH 7/8] vfio: Use vfio type1 v2 IOMMU interface +Bugzilla: 1210508 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +Upstream: 2e6e697e166568fdd09ceaa8c7c8c8c53a5e345b + +The difference between v1 and v2 is fairly subtle, simply more +deterministic behavior for unmaps. The v1 interface allows the user +to attempt to unmap sub-regions of previous mappings, returning +success with zero size if unable to comply. This was a reflection of +the underlying IOMMU API. The v2 interface requires that the user +may only unmap fully contained mappings, ie. an unmap cannot intersect +or bisect a previous mapping, but may cover multiple mappings. QEMU +never made use of the sub-region v1 support anyway, so we can support +either v1 or v2. We'll favor v2 since it's newer. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 8 ++++++-- + linux-headers/linux/vfio.h | 1 + + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 607dbf4..d06b485 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3312,7 +3312,10 @@ static int vfio_connect_container(VFIOGroup *group) + container = g_malloc0(sizeof(*container)); + container->fd = fd; + +- if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { ++ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) || ++ ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) { ++ bool v2 = !!ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU); ++ + ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); + if (ret) { + error_report("vfio: failed to set group container: %m"); +@@ -3321,7 +3324,8 @@ static int vfio_connect_container(VFIOGroup *group) + return -errno; + } + +- ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); ++ ret = ioctl(fd, VFIO_SET_IOMMU, ++ v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU); + if (ret) { + error_report("vfio: failed to set iommu for container: %m"); + g_free(container); +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index d341312..7919c76 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -22,6 +22,7 @@ + /* Extensions */ + + #define VFIO_TYPE1_IOMMU 1 ++#define VFIO_TYPE1v2_IOMMU 3 + + /* + * The IOCTL interface is designed for extensibility by embedding the +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-pci-Add-pba_offset-PCI-quirk-for-Chelsio-T5-dev.patch b/SOURCES/kvm-vfio-pci-Add-pba_offset-PCI-quirk-for-Chelsio-T5-dev.patch new file mode 100644 index 0000000..c42e302 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Add-pba_offset-PCI-quirk-for-Chelsio-T5-dev.patch @@ -0,0 +1,93 @@ +From b6a8c4f1ada2c7d31bdd2438163f11026a0a0711 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 17 Jul 2015 20:46:43 +0200 +Subject: [PATCH 2/5] vfio/pci : Add pba_offset PCI quirk for Chelsio T5 + devices + +Message-id: <20150717203953.606.815.stgit@gimli.home> +Patchwork-id: 67057 +O-Subject: [RHEL7.2 qemu-kvm PATCH] vfio/pci : Add pba_offset PCI quirk for Chelsio T5 devices +Bugzilla: 1244347 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Bandan Das +RH-Acked-by: Laszlo Ersek + +From: Gabriel Laupre + +Upstream: 43302969966bc3a95470bfc300289a83068ef5d9 + +Fix pba_offset initialization value for Chelsio T5 Virtual Function +device. The T5 hardware has a bug in it where it reports a Pending Interrupt +Bit Array Offset of 0x8000 for its SR-IOV Virtual Functions instead +of the 0x1000 that the hardware actually uses internally. As the hardware +doesn't return the correct pba_offset value, add a quirk to instead +return a hardcoded value of 0x1000 when a Chelsio T5 VF device is +detected. + +This bug has been fixed in the Chelsio's next chip series T6 but there are +no plans to respin the T5 ASIC for this bug. It is just documented in the +T5 Errata and left it at that. + +Signed-off-by: Gabriel Laupre +Reviewed-by: Bandan Das +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 27 +++++++++++++++++++++++++++ + include/hw/pci/pci_ids.h | 2 ++ + 2 files changed, 29 insertions(+) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 118489c..36b9832 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -2466,6 +2466,33 @@ static int vfio_early_setup_msix(VFIODevice *vdev) + vdev->host.function, pos, vdev->msix->table_bar, + vdev->msix->table_offset, vdev->msix->entries); + ++ /* ++ * Test the size of the pba_offset variable and catch if it extends outside ++ * of the specified BAR. If it is the case, we need to apply a hardware ++ * specific quirk if the device is known or we have a broken configuration. ++ */ ++ if (vdev->msix->pba_offset >= ++ vdev->bars[vdev->msix->pba_bar].size) { ++ ++ PCIDevice *pdev = &vdev->pdev; ++ uint16_t vendor = pci_get_word(pdev->config + PCI_VENDOR_ID); ++ uint16_t device = pci_get_word(pdev->config + PCI_DEVICE_ID); ++ ++ /* ++ * Chelsio T5 Virtual Function devices are encoded as 0x58xx for T5 ++ * adapters. The T5 hardware returns an incorrect value of 0x8000 for ++ * the VF PBA offset while the BAR itself is only 8k. The correct value ++ * is 0x1000, so we hard code that here. ++ */ ++ if (vendor == PCI_VENDOR_ID_CHELSIO && (device & 0xff00) == 0x5800) { ++ vdev->msix->pba_offset = 0x1000; ++ } else { ++ error_report("vfio: Hardware reports invalid configuration, " ++ "MSIX PBA outside of specified BAR"); ++ return -EINVAL; ++ } ++ } ++ + return 0; + } + +diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h +index d8dc2f1..3792255 100644 +--- a/include/hw/pci/pci_ids.h ++++ b/include/hw/pci/pci_ids.h +@@ -102,6 +102,8 @@ + #define PCI_VENDOR_ID_ENSONIQ 0x1274 + #define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000 + ++#define PCI_VENDOR_ID_CHELSIO 0x1425 ++ + #define PCI_VENDOR_ID_FREESCALE 0x1957 + #define PCI_DEVICE_ID_MPC8533E 0x0030 + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-pci-Enable-device-request-notification-support.patch b/SOURCES/kvm-vfio-pci-Enable-device-request-notification-support.patch new file mode 100644 index 0000000..090a99c --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Enable-device-request-notification-support.patch @@ -0,0 +1,201 @@ +From 3e7a0ab48e4cd233caf8ab9e2593d1d2978bad9d Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:34:19 +0200 +Subject: [PATCH 08/14] vfio-pci: Enable device request notification support + +Message-id: <20150410163419.15324.17072.stgit@gimli.home> +Patchwork-id: 64788 +O-Subject: [RHEL7.2 qemu-kvm PATCH 8/8] vfio-pci: Enable device request notification support +Bugzilla: 1210509 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +Upstream: 47cbe50cc8d8e59129311bcdb827e1116e935bde + +Linux v4.0-rc1 vfio-pci introduced a new virtual interrupt to allow +the kernel to request a device from the user. When signaled, QEMU +will by default attmempt to hot-unplug the device. This is a one- +shot attempt with the expectation that the kernel will continue to +poll for the device if it is not returned. Returning the device when +requested is the expected standard model of cooperative usage, but we +also add an option option to disable this feature. Initially this +opt-out is set as an experimental option because we really should +honor kernel requests for the device. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 100 +++++++++++++++++++++++++++++++++++++++++++++ + linux-headers/linux/vfio.h | 1 + + 2 files changed, 101 insertions(+) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index d06b485..cbc9d8a 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -195,14 +195,18 @@ typedef struct VFIODevice { + QLIST_ENTRY(VFIODevice) next; + struct VFIOGroup *group; + EventNotifier err_notifier; ++ EventNotifier req_notifier; + uint32_t features; + #define VFIO_FEATURE_ENABLE_VGA_BIT 0 + #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) ++#define VFIO_FEATURE_ENABLE_REQ_BIT 1 ++#define VFIO_FEATURE_ENABLE_REQ (1 << VFIO_FEATURE_ENABLE_REQ_BIT) + int32_t bootindex; + uint8_t pm_cap; + bool reset_works; + bool has_vga; + bool pci_aer; ++ bool req_enabled; + bool has_flr; + bool has_pm_reset; + bool needs_reset; +@@ -3595,6 +3599,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) + + vdev->has_vga = true; + } ++ + irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); +@@ -3737,6 +3742,97 @@ static void vfio_unregister_err_notifier(VFIODevice *vdev) + event_notifier_cleanup(&vdev->err_notifier); + } + ++static void vfio_req_notifier_handler(void *opaque) ++{ ++ VFIODevice *vdev = opaque; ++ ++ if (!event_notifier_test_and_clear(&vdev->req_notifier)) { ++ return; ++ } ++ ++ qdev_unplug(&vdev->pdev.qdev, NULL); ++} ++ ++static void vfio_register_req_notifier(VFIODevice *vdev) ++{ ++ struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info), ++ .index = VFIO_PCI_REQ_IRQ_INDEX }; ++ int argsz; ++ struct vfio_irq_set *irq_set; ++ int32_t *pfd; ++ ++ if (!(vdev->features & VFIO_FEATURE_ENABLE_REQ)) { ++ return; ++ } ++ ++ if (ioctl(vdev->fd, ++ VFIO_DEVICE_GET_IRQ_INFO, &irq_info) < 0 || irq_info.count < 1) { ++ return; ++ } ++ ++ if (event_notifier_init(&vdev->req_notifier, 0)) { ++ error_report("vfio: Unable to init event notifier for device request"); ++ return; ++ } ++ ++ argsz = sizeof(*irq_set) + sizeof(*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_REQ_IRQ_INDEX; ++ irq_set->start = 0; ++ irq_set->count = 1; ++ pfd = (int32_t *)&irq_set->data; ++ ++ *pfd = event_notifier_get_fd(&vdev->req_notifier); ++ qemu_set_fd_handler(*pfd, vfio_req_notifier_handler, NULL, vdev); ++ ++ if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { ++ error_report("vfio: Failed to set up device request notification"); ++ qemu_set_fd_handler(*pfd, NULL, NULL, vdev); ++ event_notifier_cleanup(&vdev->req_notifier); ++ } else { ++ vdev->req_enabled = true; ++ } ++ ++ g_free(irq_set); ++} ++ ++static void vfio_unregister_req_notifier(VFIODevice *vdev) ++{ ++ int argsz; ++ struct vfio_irq_set *irq_set; ++ int32_t *pfd; ++ ++ if (!vdev->req_enabled) { ++ return; ++ } ++ ++ argsz = sizeof(*irq_set) + sizeof(*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_REQ_IRQ_INDEX; ++ irq_set->start = 0; ++ irq_set->count = 1; ++ pfd = (int32_t *)&irq_set->data; ++ *pfd = -1; ++ ++ if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { ++ error_report("vfio: Failed to de-assign device request fd: %m"); ++ } ++ g_free(irq_set); ++ qemu_set_fd_handler(event_notifier_get_fd(&vdev->req_notifier), ++ NULL, NULL, vdev); ++ event_notifier_cleanup(&vdev->req_notifier); ++ ++ vdev->req_enabled = false; ++} ++ + static int vfio_initfn(PCIDevice *pdev) + { + VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev); +@@ -3889,6 +3985,7 @@ static int vfio_initfn(PCIDevice *pdev) + + add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL); + vfio_register_err_notifier(vdev); ++ vfio_register_req_notifier(vdev); + + return 0; + +@@ -3908,6 +4005,7 @@ static void vfio_exitfn(PCIDevice *pdev) + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOGroup *group = vdev->group; + ++ vfio_unregister_req_notifier(vdev); + vfio_unregister_err_notifier(vdev); + pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + vfio_disable_interrupts(vdev); +@@ -3962,6 +4060,8 @@ static Property vfio_pci_dev_properties[] = { + intx.mmap_timeout, 1100), + DEFINE_PROP_BIT("x-vga", VFIODevice, features, + VFIO_FEATURE_ENABLE_VGA_BIT, false), ++ DEFINE_PROP_BIT("x-req", VFIODevice, features, ++ VFIO_FEATURE_ENABLE_REQ_BIT, true), + DEFINE_PROP_INT32("bootindex", VFIODevice, bootindex, -1), + /* + * TODO - support passed fds... is this necessary? +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index 7919c76..d197fd4 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -321,6 +321,7 @@ enum { + VFIO_PCI_MSI_IRQ_INDEX, + VFIO_PCI_MSIX_IRQ_INDEX, + VFIO_PCI_ERR_IRQ_INDEX, ++ VFIO_PCI_REQ_IRQ_INDEX, + VFIO_PCI_NUM_IRQS + }; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-pci-Fix-BAR-size-overflow.patch b/SOURCES/kvm-vfio-pci-Fix-BAR-size-overflow.patch new file mode 100644 index 0000000..dcb01a2 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Fix-BAR-size-overflow.patch @@ -0,0 +1,57 @@ +From 27b471e574edcee7ac065a7a46f558dca0fd7bf0 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:34:08 +0200 +Subject: [PATCH 06/14] vfio-pci: Fix BAR size overflow + +Message-id: <20150410163408.15324.43004.stgit@gimli.home> +Patchwork-id: 64792 +O-Subject: [RHEL7.2 qemu-kvm PATCH 6/8] vfio-pci: Fix BAR size overflow +Bugzilla: 1181267 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +Upstream: 29c6e6df492d81b1843e5dd999171bb84c6effea + +We use an unsigned int when working with the PCI BAR size, which can +obviously overflow if the BAR is 4GB or larger. This needs to change +to a fixed length uint64_t. A similar issue is possible, though even +more unlikely, when mapping the region above an MSI-X table. The +start of the MSI-X vector table must be below 4GB, but the end, and +therefore the start of the next mapping region, could still land at +4GB. + +Suggested-by: Nishank Trivedi +Signed-off-by: Alex Williamson +Reviewed-by: Don Slutz +Tested-by: Alexey Kardashevskiy +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index f6e019c..607dbf4 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -2579,7 +2579,7 @@ empty_region: + static void vfio_map_bar(VFIODevice *vdev, int nr) + { + VFIOBAR *bar = &vdev->bars[nr]; +- unsigned size = bar->size; ++ uint64_t size = bar->size; + char name[64]; + uint32_t pci_bar; + uint8_t type; +@@ -2628,7 +2628,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) + } + + if (vdev->msix && vdev->msix->table_bar == nr) { +- unsigned start; ++ uint64_t start; + + start = TARGET_PAGE_ALIGN(vdev->msix->table_offset + + (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE)); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-pci-Fix-error-path-sign.patch b/SOURCES/kvm-vfio-pci-Fix-error-path-sign.patch new file mode 100644 index 0000000..261d929 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Fix-error-path-sign.patch @@ -0,0 +1,45 @@ +From ad2855430b1fcbd4566af464120892a32ce7d9f8 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 1 May 2015 18:10:44 +0200 +Subject: [PATCH 10/14] vfio-pci: Fix error path sign + +Message-id: <20150501180951.31395.33354.stgit@gimli.home> +Patchwork-id: 64973 +O-Subject: [RHEL7.2 qemu-kvm PATCH 10/8] vfio-pci: Fix error path sign +Bugzilla: 1210504 +RH-Acked-by: Bandan Das +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek + +This is an impossible error path due to the fact that we're reading a +kernel provided, rather than user provided link, which will certainly +always fit in PATH_MAX. Currently it returns a fixed 26 char path +plus %d group number, which typically maxes out at double digits. +However, the caller of the initfn certainly expects a less-than zero +return value on error, not just a non-zero value. Therefore we +should correct the sign here. + +Reported-by: Laszlo Ersek +Reviewed-by: Laszlo Ersek +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index e6f96db..118489c 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3870,7 +3870,7 @@ static int vfio_initfn(PCIDevice *pdev) + len = readlink(path, iommu_group_path, sizeof(path)); + if (len <= 0 || len >= sizeof(path)) { + error_report("vfio: error no iommu_group for device"); +- return len < 0 ? -errno : ENAMETOOLONG; ++ return len < 0 ? -errno : -ENAMETOOLONG; + } + + iommu_group_path[len] = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-pci-Further-fix-BAR-size-overflow.patch b/SOURCES/kvm-vfio-pci-Further-fix-BAR-size-overflow.patch new file mode 100644 index 0000000..cb1f866 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Further-fix-BAR-size-overflow.patch @@ -0,0 +1,59 @@ +From 46edd2ae852e19ee3a1b473be949691c6ce5694d Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 1 May 2015 18:09:33 +0200 +Subject: [PATCH 09/14] vfio-pci: Further fix BAR size overflow + +Message-id: <20150501180733.31334.63326.stgit@gimli.home> +Patchwork-id: 64972 +O-Subject: [RHEL7.2 qemu-kvm PATCH 9/8] vfio-pci: Further fix BAR size overflow +Bugzilla: 1181267 +RH-Acked-by: Thomas Huth +RH-Acked-by: Bandan Das +RH-Acked-by: Laszlo Ersek + +Bugzilla: 1181267 +Upstream: 07ceaf98800519ef9c5dc893af00f1fe1f9144e4 + +In an analysis by Laszlo, the resulting type of our calculation for +the end of the MSI-X table, and thus the start of memory after the +table, is uint32_t. We're therefore not correctly preventing the +corner case overflow that we intended to fix here where a BAR >=4G +could place the MSI-X table to end exactly at the 4G boundary. The +MSI-X table offset is defined by the hardware spec to 32bits, so we +simply use a cast rather than changing data structure types. This +scenario is purely theoretically, typically the MSI-X table is located +at the front of the BAR. + +Reported-by: Laszlo Ersek +Reviewed-by: Laszlo Ersek +Signed-off-by: Alex Williamson +--- + +Brew for series including 9 & 10: + +http://brewweb.devel.redhat.com/brew/taskinfo?taskID=9082147 + + hw/misc/vfio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index cbc9d8a..e6f96db 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -2634,7 +2634,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) + if (vdev->msix && vdev->msix->table_bar == nr) { + uint64_t start; + +- start = TARGET_PAGE_ALIGN(vdev->msix->table_offset + ++ start = TARGET_PAGE_ALIGN((uint64_t)vdev->msix->table_offset + + (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE)); + + size = start < bar->size ? bar->size - start : 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-use-correct-runstate.patch b/SOURCES/kvm-vfio-use-correct-runstate.patch new file mode 100644 index 0000000..b77de61 --- /dev/null +++ b/SOURCES/kvm-vfio-use-correct-runstate.patch @@ -0,0 +1,44 @@ +From 78d0d122c47898c20a5209d0020674d28b42c513 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:34:02 +0200 +Subject: [PATCH 05/14] vfio: use correct runstate + +Message-id: <20150410163402.15324.34238.stgit@gimli.home> +Patchwork-id: 64791 +O-Subject: [RHEL7.2 qemu-kvm PATCH 5/8] vfio: use correct runstate +Bugzilla: 1210505 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +Upstream: ba29776fd8160a5c1c1892af5e237fc37aec3cf7 + +io-error is for block device errors; it should always be preceded +by a BLOCK_IO_ERROR event. I think vfio wants to use +RUN_STATE_INTERNAL_ERROR instead. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 81e6594..f6e019c 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3650,7 +3650,7 @@ static void vfio_err_notifier_handler(void *opaque) + __func__, vdev->host.domain, vdev->host.bus, + vdev->host.slot, vdev->host.function); + +- vm_stop(RUN_STATE_IO_ERROR); ++ vm_stop(RUN_STATE_INTERNAL_ERROR); + } + + /* +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-warn-if-host-device-rom-can-t-be-read.patch b/SOURCES/kvm-vfio-warn-if-host-device-rom-can-t-be-read.patch new file mode 100644 index 0000000..a965b8f --- /dev/null +++ b/SOURCES/kvm-vfio-warn-if-host-device-rom-can-t-be-read.patch @@ -0,0 +1,51 @@ +From 5bf64f8c7302964bd5fd208d9db9fa38ee96e0fa Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:33:39 +0200 +Subject: [PATCH 01/14] vfio: warn if host device rom can't be read + +Message-id: <20150410163339.15324.77513.stgit@gimli.home> +Patchwork-id: 64789 +O-Subject: [RHEL7.2 qemu-kvm PATCH 1/8] vfio: warn if host device rom can't be read +Bugzilla: 1210503 +RH-Acked-by: Thomas Huth +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das + +From: Bandan Das + +Upstream: d20b43dfea1587b561aae17e4fa0f7407779d253 + +If the device rom can't be read, report an error to the +user. This alerts the user that the device has a bad +state that is causing rom read failure or option rom +loading has been disabled from the device boot menu +(among other reasons). + +Signed-off-by: Bandan Das +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 40b0923..c9dbc28 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -1197,6 +1197,13 @@ static void vfio_pci_load_rom(VFIODevice *vdev) + vdev->rom_offset = reg_info.offset; + + if (!vdev->rom_size) { ++ error_report("vfio-pci: Cannot read device rom at " ++ "%04x:%02x:%02x.%x\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ error_printf("Device option ROM contents are probably invalid " ++ "(check dmesg).\nSkip option ROM probe with rombar=0, " ++ "or load from file with romfile=\n"); + return; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-net-drop-assert-on-vm-stop.patch b/SOURCES/kvm-virtio-net-drop-assert-on-vm-stop.patch new file mode 100644 index 0000000..6b5c6fe --- /dev/null +++ b/SOURCES/kvm-virtio-net-drop-assert-on-vm-stop.patch @@ -0,0 +1,47 @@ +From 83375cf67c9567c94808e70fa9def3383a97320c Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Fri, 19 Dec 2014 13:51:53 +0100 +Subject: [PATCH 02/16] virtio-net: drop assert on vm stop + +Message-id: <1418997113-32517-1-git-send-email-akong@redhat.com> +Patchwork-id: 62996 +O-Subject: [RHEL-7.2 qemu-kvm PATCH] virtio-net: drop assert on vm stop +Bugzilla: 1139562 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Fam Zheng +RH-Acked-by: Xiao Wang + +From: Michael S. Tsirkin + +On vm stop, vm_running state set to stopped +before device is notified, so callbacks can get envoked with +vm_running = false; and this is not an error. + +Cc: qemu-stable@nongnu.org +Acked-by: Jason Wang +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 131c5221fe25a9547c4a388a3d26ff7fd14843e5) + +Signed-off-by: Amos Kong +Signed-off-by: Miroslav Rezanina +--- + hw/net/virtio-net.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 4a50869..3fde455 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1025,8 +1025,6 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) + return num_packets; + } + +- assert(vdev->vm_running); +- + if (q->async_tx.elem.out_num) { + virtio_queue_set_notification(q->tx_vq, 0); + return num_packets; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-scsi-use-virtqueue_map_sg-when-loading-reques.patch b/SOURCES/kvm-virtio-scsi-use-virtqueue_map_sg-when-loading-reques.patch new file mode 100644 index 0000000..3d6296d --- /dev/null +++ b/SOURCES/kvm-virtio-scsi-use-virtqueue_map_sg-when-loading-reques.patch @@ -0,0 +1,57 @@ +From c732ec0ec457f0cb003b3b1db56c0bd96432baac Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 3 Aug 2015 16:51:19 +0200 +Subject: [PATCH 05/13] virtio-scsi: use virtqueue_map_sg() when loading + requests + +Message-id: <1438620680-24121-2-git-send-email-stefanha@redhat.com> +Patchwork-id: 67255 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/2] virtio-scsi: use virtqueue_map_sg() when loading requests +Bugzilla: 1249718 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Fam Zheng +RH-Acked-by: Paolo Bonzini + +The VirtQueueElement struct is serialized during migration but the +in_sg[]/out_sg[] iovec arrays are not usable on the destination host +because the pointers are meaningless. + +Use virtqueue_map_sg() to refresh in_sg[]/out_sg[] to valid pointers +based on in_addr[]/out_addr[] hwaddrs. + +Cc: Paolo Bonzini +Signed-off-by: Stefan Hajnoczi +Message-Id: <1438262173-11546-2-git-send-email-stefanha@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1cc933453bf2baae1feb7c8e757bdfd0ef639002) + +Conficts: + * Context conflict because upstream has error handling code for + virtio_scsi_parse_req(). + +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Miroslav Rezanina +--- + hw/scsi/virtio-scsi.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index cda8f8a..8232fc9 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -154,6 +154,12 @@ static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq) + #endif + assert(req->elem.in_num <= ARRAY_SIZE(req->elem.in_sg)); + assert(req->elem.out_num <= ARRAY_SIZE(req->elem.out_sg)); ++ ++ virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr, ++ req->elem.in_num, 1); ++ virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr, ++ req->elem.out_num, 0); ++ + virtio_scsi_parse_req(s, vs->cmd_vqs[n], req); + + scsi_req_ref(sreq); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vmdk-Fix-overflow-if-l1_size-is-0x20000000.patch b/SOURCES/kvm-vmdk-Fix-overflow-if-l1_size-is-0x20000000.patch new file mode 100644 index 0000000..a0888b4 --- /dev/null +++ b/SOURCES/kvm-vmdk-Fix-overflow-if-l1_size-is-0x20000000.patch @@ -0,0 +1,62 @@ +From 77824d3e0c00074d30f345be594d4ca941585edd Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 1 Jun 2015 08:23:51 +0200 +Subject: [PATCH 01/30] vmdk: Fix overflow if l1_size is 0x20000000 + +Message-id: <1433147031-14770-1-git-send-email-famz@redhat.com> +Patchwork-id: 65160 +O-Subject: [RHEL-7.2 qemu-kvm PATCH] vmdk: Fix overflow if l1_size is 0x20000000 +Bugzilla: 1217351 +RH-Acked-by: Max Reitz +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek + +Richard Jones caught this bug with afl fuzzer. + +In fact, that's the only possible value to overflow (extent->l1_size = +0x20000000) l1_size: + +l1_size = extent->l1_size * sizeof(long) => 0x80000000; + +g_try_malloc returns NULL because l1_size is interpreted as negative +during type casting from 'int' to 'gsize', which yields a enormous +value. Hence, by coincidence, we get a "not too bad" behavior: + +qemu-img: Could not open '/tmp/afl6.img': Could not open +'/tmp/afl6.img': Cannot allocate memory + +Values larger than 0x20000000 will be refused by the validation in +vmdk_add_extent. + +Values smaller than 0x20000000 will not overflow l1_size. + +Cc: qemu-stable@nongnu.org +Reported-by: Richard W.M. Jones +Signed-off-by: Fam Zheng +Reviewed-by: Max Reitz +Tested-by: Richard W.M. Jones +Signed-off-by: Kevin Wolf +(cherry picked from commit 13c4941cdd8685d28c7e3a09e393a5579b58db46) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 24e9458..6b015ab 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -451,7 +451,8 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, + Error **errp) + { + int ret; +- int l1_size, i; ++ size_t l1_size; ++ int i; + + /* read the L1 table */ + l1_size = extent->l1_size * sizeof(uint32_t); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vpc-Handle-failure-for-potentially-large-allocations.patch b/SOURCES/kvm-vpc-Handle-failure-for-potentially-large-allocations.patch new file mode 100644 index 0000000..d2364cf --- /dev/null +++ b/SOURCES/kvm-vpc-Handle-failure-for-potentially-large-allocations.patch @@ -0,0 +1,51 @@ +From 46415e245ed90b1bb08ff4d67559a6c0f34cf9db Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Wed, 29 Jul 2015 16:59:53 +0200 +Subject: [PATCH 02/13] vpc: Handle failure for potentially large allocations + +Message-id: +Patchwork-id: 67196 +O-Subject: [RHEL-7.2 qemu-kvm PATCH 1/3] vpc: Handle failure for potentially large allocations +Bugzilla: 1217349 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +From: Kevin Wolf + +Some code in the block layer makes potentially huge allocations. Failure +is not completely unexpected there, so avoid aborting qemu and handle +out-of-memory situations gracefully. + +This patch addresses the allocations in the vpc block driver. + +Signed-off-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Benoit Canet +(cherry picked from commit 5fb09cd5867aabf26d5b85b0913dccd496b71421) +Signed-off-by: Jeff Cody +Signed-off-by: Miroslav Rezanina +--- + block/vpc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/vpc.c b/block/vpc.c +index 849501a..6fdce40 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -260,7 +260,11 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, + goto fail; + } + +- s->pagetable = qemu_blockalign(bs, s->max_table_entries * 4); ++ s->pagetable = qemu_try_blockalign(bs->file, s->max_table_entries * 4); ++ if (s->pagetable == NULL) { ++ ret = -ENOMEM; ++ goto fail; ++ } + + s->bat_offset = be64_to_cpu(dyndisk_header->table_offset); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-Clear-MTRRs-on-vCPU-reset.patch b/SOURCES/kvm-x86-Clear-MTRRs-on-vCPU-reset.patch new file mode 100644 index 0000000..4a166fc --- /dev/null +++ b/SOURCES/kvm-x86-Clear-MTRRs-on-vCPU-reset.patch @@ -0,0 +1,65 @@ +From 2f6d988d14532616d1f1f476b438b4e3295329f1 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:45:59 +0200 +Subject: [PATCH 13/14] x86: Clear MTRRs on vCPU reset + +Message-id: <20150410164559.16166.37319.stgit@gimli.home> +Patchwork-id: 64799 +O-Subject: [RHEL7.2 qemu-kvm PATCH 3/3] x86: Clear MTRRs on vCPU reset +Bugzilla: 1210510 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Upstream: 9db2efd95e13330075bff027cd682a063d725332 + +The SDM specifies (June 2014 Vol3 11.11.5): + + On a hardware reset, the P6 and more recent processors clear the + valid flags in variable-range MTRRs and clear the E flag in the + IA32_MTRR_DEF_TYPE MSR to disable all MTRRs. All other bits in the + MTRRs are undefined. + +We currently do none of that, so whatever MTRR settings you had prior +to reset is what you have after reset. Usually this doesn't matter +because KVM often ignores the guest mappings and uses write-back +anyway. However, if you have an assigned device and an IOMMU that +allows NoSnoop for that device, KVM defers to the guest memory +mappings which are now stale after reset. The result is that OVMF +rebooting on such a configuration takes a full minute to LZMA +decompress the firmware volume, a process that is nearly instant on +the initial boot. + +Signed-off-by: Alex Williamson +Reviewed-by: Laszlo Ersek +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 1507530..b76719d 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -2398,6 +2398,16 @@ static void x86_cpu_reset(CPUState *s) + cpu_breakpoint_remove_all(env, BP_CPU); + cpu_watchpoint_remove_all(env, BP_CPU); + ++ /* ++ * SDM 11.11.5 requires: ++ * - IA32_MTRR_DEF_TYPE MSR.E = 0 ++ * - IA32_MTRR_PHYSMASKn.V = 0 ++ * All other bits are undefined. For simplification, zero it all. ++ */ ++ env->mtrr_deftype = 0; ++ memset(env->mtrr_var, 0, sizeof(env->mtrr_var)); ++ memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); ++ + #if !defined(CONFIG_USER_ONLY) + /* We hard-wire the BSP to the first CPU. */ + if (s->cpu_index == 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-Use-common-variable-range-MTRR-counts.patch b/SOURCES/kvm-x86-Use-common-variable-range-MTRR-counts.patch new file mode 100644 index 0000000..5300ac8 --- /dev/null +++ b/SOURCES/kvm-x86-Use-common-variable-range-MTRR-counts.patch @@ -0,0 +1,59 @@ +From 9f6b8fe31ea92570c4e43d35abcadafea9576d89 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:45:47 +0200 +Subject: [PATCH 11/14] x86: Use common variable range MTRR counts + +Message-id: <20150410164547.16166.20530.stgit@gimli.home> +Patchwork-id: 64797 +O-Subject: [RHEL7.2 qemu-kvm PATCH 1/3] x86: Use common variable range MTRR counts +Bugzilla: 1210510 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Upstream: d8b5c67b05420d966664664ff287af05b884bdd1 + +We currently define the number of variable range MTRR registers as 8 +in the CPUX86State structure and vmstate, but use MSR_MTRRcap_VCNT +(also 8) to report to guests the number available. Change this to +use MSR_MTRRcap_VCNT consistently. + +Signed-off-by: Alex Williamson +Reviewed-by: Laszlo Ersek +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.h | 2 +- + target-i386/machine.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 207645c..763fbf2 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -886,7 +886,7 @@ typedef struct CPUX86State { + /* MTRRs */ + uint64_t mtrr_fixed[11]; + uint64_t mtrr_deftype; +- MTRRVar mtrr_var[8]; ++ MTRRVar mtrr_var[MSR_MTRRcap_VCNT]; + + /* For KVM */ + uint32_t mp_state; +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 87fd496..4c1ead4 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -647,7 +647,7 @@ const VMStateDescription vmstate_x86_cpu = { + /* MTRRs */ + VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8), + VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8), +- VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, 8, 8), ++ VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, MSR_MTRRcap_VCNT, 8), + /* KVM-related states */ + VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9), + VMSTATE_UINT32_V(env.mp_state, X86CPU, 9), +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-kvm-Add-MTRR-support-for-kvm_get-put_msrs.patch b/SOURCES/kvm-x86-kvm-Add-MTRR-support-for-kvm_get-put_msrs.patch new file mode 100644 index 0000000..3b06241 --- /dev/null +++ b/SOURCES/kvm-x86-kvm-Add-MTRR-support-for-kvm_get-put_msrs.patch @@ -0,0 +1,213 @@ +From 7a7ee1756f309f4f69ed9929b2d7a652f9a879b2 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 10 Apr 2015 16:45:53 +0200 +Subject: [PATCH 12/14] x86: kvm: Add MTRR support for kvm_get|put_msrs() + +Message-id: <20150410164553.16166.97985.stgit@gimli.home> +Patchwork-id: 64798 +O-Subject: [RHEL7.2 qemu-kvm PATCH 2/3] x86: kvm: Add MTRR support for kvm_get|put_msrs() +Bugzilla: 1210510 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Upstream: d1ae67f626c5ed5729e1d8212834291b409d26df + +The MTRR state in KVM currently runs completely independent of the +QEMU state in CPUX86State.mtrr_*. This means that on migration, the +target loses MTRR state from the source. Generally that's ok though +because KVM ignores it and maps everything as write-back anyway. The +exception to this rule is when we have an assigned device and an IOMMU +that doesn't promote NoSnoop transactions from that device to be cache +coherent. In that case KVM trusts the guest mapping of memory as +configured in the MTRR. + +This patch updates kvm_get|put_msrs() so that we retrieve the actual +vCPU MTRR settings and therefore keep CPUX86State synchronized for +migration. kvm_put_msrs() is also used on vCPU reset and therefore +allows future modificaitons of MTRR state at reset to be realized. + +Note that the entries array used by both functions was already +slightly undersized for holding every possible MSR, so this patch +increases it beyond the 28 new entries necessary for MTRR state. + +Signed-off-by: Alex Williamson +Reviewed-by: Laszlo Ersek +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.h | 2 ++ + target-i386/kvm.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 101 insertions(+), 2 deletions(-) + +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 763fbf2..e9edd3d 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -332,6 +332,8 @@ + #define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) + #define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) + ++#define MSR_MTRRphysIndex(addr) ((((addr) & ~1u) - 0x200) / 2) ++ + #define MSR_MTRRfix64K_00000 0x250 + #define MSR_MTRRfix16K_80000 0x258 + #define MSR_MTRRfix16K_A0000 0x259 +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index 65362ac..97ae345 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -73,6 +73,7 @@ static int lm_capable_kernel; + static bool has_msr_hv_hypercall; + static bool has_msr_hv_vapic; + static bool has_msr_hv_tsc; ++static bool has_msr_mtrr; + + static bool has_msr_architectural_pmu; + static uint32_t num_architectural_pmu_counters; +@@ -711,6 +712,10 @@ int kvm_arch_init_vcpu(CPUState *cs) + env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); + } + ++ if (env->features[FEAT_1_EDX] & CPUID_MTRR) { ++ has_msr_mtrr = true; ++ } ++ + return 0; + } + +@@ -1117,7 +1122,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + CPUX86State *env = &cpu->env; + struct { + struct kvm_msrs info; +- struct kvm_msr_entry entries[100]; ++ struct kvm_msr_entry entries[150]; + } msr_data; + struct kvm_msr_entry *msrs = msr_data.entries; + int n = 0, i; +@@ -1219,6 +1224,37 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_REFERENCE_TSC, + env->msr_hv_tsc); + } ++ if (has_msr_mtrr) { ++ kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix64K_00000, env->mtrr_fixed[0]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix16K_80000, env->mtrr_fixed[1]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix16K_A0000, env->mtrr_fixed[2]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_C0000, env->mtrr_fixed[3]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_C8000, env->mtrr_fixed[4]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_D0000, env->mtrr_fixed[5]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_D8000, env->mtrr_fixed[6]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_E0000, env->mtrr_fixed[7]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_E8000, env->mtrr_fixed[8]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_F0000, env->mtrr_fixed[9]); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRfix4K_F8000, env->mtrr_fixed[10]); ++ for (i = 0; i < MSR_MTRRcap_VCNT; i++) { ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRphysBase(i), env->mtrr_var[i].base); ++ kvm_msr_entry_set(&msrs[n++], ++ MSR_MTRRphysMask(i), env->mtrr_var[i].mask); ++ } ++ } + } + if (env->mcg_cap) { + int i; +@@ -1418,7 +1454,7 @@ static int kvm_get_msrs(X86CPU *cpu) + CPUX86State *env = &cpu->env; + struct { + struct kvm_msrs info; +- struct kvm_msr_entry entries[100]; ++ struct kvm_msr_entry entries[150]; + } msr_data; + struct kvm_msr_entry *msrs = msr_data.entries; + int ret, i, n; +@@ -1500,6 +1536,24 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_hv_tsc) { + msrs[n++].index = HV_X64_MSR_REFERENCE_TSC; + } ++ if (has_msr_mtrr) { ++ msrs[n++].index = MSR_MTRRdefType; ++ msrs[n++].index = MSR_MTRRfix64K_00000; ++ msrs[n++].index = MSR_MTRRfix16K_80000; ++ msrs[n++].index = MSR_MTRRfix16K_A0000; ++ msrs[n++].index = MSR_MTRRfix4K_C0000; ++ msrs[n++].index = MSR_MTRRfix4K_C8000; ++ msrs[n++].index = MSR_MTRRfix4K_D0000; ++ msrs[n++].index = MSR_MTRRfix4K_D8000; ++ msrs[n++].index = MSR_MTRRfix4K_E0000; ++ msrs[n++].index = MSR_MTRRfix4K_E8000; ++ msrs[n++].index = MSR_MTRRfix4K_F0000; ++ msrs[n++].index = MSR_MTRRfix4K_F8000; ++ for (i = 0; i < MSR_MTRRcap_VCNT; i++) { ++ msrs[n++].index = MSR_MTRRphysBase(i); ++ msrs[n++].index = MSR_MTRRphysMask(i); ++ } ++ } + + msr_data.info.nmsrs = n; + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); +@@ -1614,6 +1668,49 @@ static int kvm_get_msrs(X86CPU *cpu) + case HV_X64_MSR_REFERENCE_TSC: + env->msr_hv_tsc = msrs[i].data; + break; ++ case MSR_MTRRdefType: ++ env->mtrr_deftype = msrs[i].data; ++ break; ++ case MSR_MTRRfix64K_00000: ++ env->mtrr_fixed[0] = msrs[i].data; ++ break; ++ case MSR_MTRRfix16K_80000: ++ env->mtrr_fixed[1] = msrs[i].data; ++ break; ++ case MSR_MTRRfix16K_A0000: ++ env->mtrr_fixed[2] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_C0000: ++ env->mtrr_fixed[3] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_C8000: ++ env->mtrr_fixed[4] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_D0000: ++ env->mtrr_fixed[5] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_D8000: ++ env->mtrr_fixed[6] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_E0000: ++ env->mtrr_fixed[7] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_E8000: ++ env->mtrr_fixed[8] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_F0000: ++ env->mtrr_fixed[9] = msrs[i].data; ++ break; ++ case MSR_MTRRfix4K_F8000: ++ env->mtrr_fixed[10] = msrs[i].data; ++ break; ++ case MSR_MTRRphysBase(0) ... MSR_MTRRphysMask(MSR_MTRRcap_VCNT - 1): ++ if (index & 1) { ++ env->mtrr_var[MSR_MTRRphysIndex(index)].mask = msrs[i].data; ++ } else { ++ env->mtrr_var[MSR_MTRRphysIndex(index)].base = msrs[i].data; ++ } ++ break; + } + } + +-- +1.8.3.1 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 0820ccb..caab349 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -16,6 +16,7 @@ %ifnarch s390 s390x %global have_librdma 1 + %global have_tcmalloc 1 %endif %ifnarch x86_64 @@ -36,8 +37,11 @@ %endif %ifarch ppc %global kvm_target ppc - %endif +%ifarch aarch64 + %global kvm_target aarch64 +%endif + #Versions of various parts: %define pkgname qemu-kvm @@ -72,7 +76,7 @@ Obsoletes: %1 < %{obsoletes_version} \ Summary: QEMU is a FAST! processor emulator Name: %{pkgname}%{?pkgsuffix} Version: 1.5.3 -Release: 86%{?dist}.8 +Release: 105%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 10 License: GPLv2+ and LGPLv2+ and BSD @@ -2833,38 +2837,330 @@ Patch1390: kvm-cirrus-fix-blit-region-check.patch Patch1391: kvm-cirrus-don-t-overflow-CirrusVGAState-cirrus_bltbuf.patch # For bz#1198958 - Add rhel-6.6.0 machine type to RHEL 7.1.z to support RHEL 6.6 to RHEL 7.1 live migration Patch1392: kvm-pc-add-rhel6.6.0-machine-type.patch -# For bz#1219269 - EMBARGOED CVE-2015-3456 qemu-kvm: qemu: floppy disk controller flaw [rhel-7.1.z] -Patch1393: kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch -# For bz#1233643 - [abrt] qemu-kvm: bdrv_error_action(): qemu-kvm killed by SIGABRT -Patch1394: kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch -# For bz#1243689 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.1.z] -Patch1395: kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch -# For bz#1243689 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.1.z] -Patch1396: kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch -# For bz#1243689 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.1.z] -Patch1397: kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch -# For bz#1243726 - CVE-2015-3214 qemu-kvm: qemu: i8254: out-of-bounds memory access in pit_ioport_read function [rhel-7.1.z] -Patch1398: kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1399: kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1400: kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1401: kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1402: kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1403: kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1404: kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch -# For bz#1248764 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z] -Patch1405: kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch -# For bz#1205050 - CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.1.z] -Patch1406: kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch -# For bz#1205050 - CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.1.z] -Patch1407: kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch -# For bz#1273098 - qemu-kvm build failure race condition in tests/ide-test -Patch1408: kvm-qtest-ide-test-disable-flush-test.patch +# For bz#1155671 - [Fujitsu 7.2 FEAT]: QEMU: Add tracepoints in system shutdown +Patch1393: kvm-trace-add-qemu_system_powerdown_request-and-qemu_sys.patch +# For bz#1139562 - qemu-kvm with vhost=off and sndbuf=100 crashed when stop it during pktgen test from guest to host +Patch1394: kvm-virtio-net-drop-assert-on-vm-stop.patch +# For bz#1086168 - qemu-kvm can not cancel migration in src host when network of dst host failed +Patch1395: kvm-socket-shutdown.patch +# For bz#1086168 - qemu-kvm can not cancel migration in src host when network of dst host failed +Patch1396: kvm-Handle-bi-directional-communication-for-fd-migration.patch +# For bz#1086168 - qemu-kvm can not cancel migration in src host when network of dst host failed +Patch1397: kvm-migration_cancel-shutdown-migration-socket.patch +# For bz#1032412 - opening read-only iscsi lun as read-write should fail +Patch1398: kvm-iscsi-Refuse-to-open-as-writable-if-the-LUN-is-write.patch +# For bz#1176283 - [migration]migration failed when configure guest with OVMF bios + machine type=rhel6.5.0 +Patch1399: kvm-main-set-current_machine-before-calling-machine-init.patch +# For bz#1176283 - [migration]migration failed when configure guest with OVMF bios + machine type=rhel6.5.0 +Patch1400: kvm-pc_sysfw-prevent-pflash-and-or-mis-sized-firmware-fo.patch +# For bz#892258 - ide CDROM io/data errors after migration +Patch1401: kvm-Restore-atapi_dma-flag-across-migration.patch +# For bz#892258 - ide CDROM io/data errors after migration +Patch1402: kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch +Patch1403: kvm-build-reenable-local-builds-to-pass-enable-debug-RHE.patch +# For bz#1184363 - Qemu process fails to start with a multipath device with all paths failed +Patch1404: kvm-raw-posix-Fail-gracefully-if-no-working-alignment-is.patch +# For bz#1184363 - Qemu process fails to start with a multipath device with all paths failed +Patch1405: kvm-block-Add-Error-argument-to-bdrv_refresh_limits.patch +# For bz#828493 - [Hitachi 7.2 FEAT] Extract guest memory dump from qemu-kvm core +Patch1406: kvm-Python-lang-gdb-script-to-extract-x86_64-guest-vmcor.patch +# For bz#1210503 - vfio improve PCI ROM loading error handling +Patch1407: kvm-vfio-warn-if-host-device-rom-can-t-be-read.patch +# For bz#1210503 - vfio improve PCI ROM loading error handling +Patch1408: kvm-vfio-Do-not-reattempt-a-failed-rom-read.patch +# For bz#1210503 - vfio improve PCI ROM loading error handling +Patch1409: kvm-vfio-Correction-in-vfio_rom_read-when-attempting-rom.patch +# For bz#1210504 - vfio: Fix overrun after readlink() fills buffer completely +Patch1410: kvm-vfio-Fix-overrun-after-readlink-fills-buffer-complet.patch +# For bz#1210505 - vfio: use correct runstate +Patch1411: kvm-vfio-use-correct-runstate.patch +# For bz#1181267 - vfio-pci: Fix BAR size overflow +Patch1412: kvm-vfio-pci-Fix-BAR-size-overflow.patch +# For bz#1210508 - vfio: Use vfio type1 v2 IOMMU interface +Patch1413: kvm-vfio-Use-vfio-type1-v2-IOMMU-interface.patch +# For bz#1210509 - vfio-pci: Enable device request notification support +Patch1414: kvm-vfio-pci-Enable-device-request-notification-support.patch +# For bz#1181267 - vfio-pci: Fix BAR size overflow +Patch1415: kvm-vfio-pci-Further-fix-BAR-size-overflow.patch +# For bz#1210504 - vfio: Fix overrun after readlink() fills buffer completely +Patch1416: kvm-vfio-pci-Fix-error-path-sign.patch +# For bz#1210510 - Sync MTRRs with KVM and disable on reset +Patch1417: kvm-x86-Use-common-variable-range-MTRR-counts.patch +# For bz#1210510 - Sync MTRRs with KVM and disable on reset +Patch1418: kvm-x86-kvm-Add-MTRR-support-for-kvm_get-put_msrs.patch +# For bz#1210510 - Sync MTRRs with KVM and disable on reset +Patch1419: kvm-x86-Clear-MTRRs-on-vCPU-reset.patch +# For bz#1206497 - CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.2] +Patch1420: kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch +# For bz#1206497 - CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.2] +Patch1421: kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch +# For bz#1200295 - QEMU segfault when doing unaligned zero write to non-512 disk +Patch1422: kvm-qemu-iotests-Test-unaligned-4k-zero-write.patch +# For bz#1200295 - QEMU segfault when doing unaligned zero write to non-512 disk +Patch1423: kvm-block-Fix-NULL-deference-for-unaligned-write-if-qiov.patch +# For bz#1200295 - QEMU segfault when doing unaligned zero write to non-512 disk +Patch1424: kvm-qemu-iotests-Test-unaligned-sub-block-zero-write.patch +# For bz#1219270 - CVE-2015-3456 qemu-kvm: qemu: floppy disk controller flaw [rhel-7.2] +Patch1425: kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch +# For bz#1208808 - creating second and further snapshot takes ages +Patch1426: kvm-qcow2-Pass-discard-type-to-qcow2_discard_clusters.patch +# For bz#1208808 - creating second and further snapshot takes ages +Patch1427: kvm-qcow2-Discard-VM-state-in-active-L1-after-creating-s.patch +# For bz#1217850 - qemu-kvm: Enable build on aarch64 +Patch1428: kvm-configure-Require-libfdt-for-arm-ppc-microblaze-soft.patch +# For bz#1217850 - qemu-kvm: Enable build on aarch64 +Patch1429: kvm-configure-Add-handling-code-for-AArch64-targets.patch +# For bz#1217850 - qemu-kvm: Enable build on aarch64 +Patch1430: kvm-configure-permit-compilation-on-arm-aarch64.patch +# For bz#1217850 - qemu-kvm: Enable build on aarch64 +Patch1431: kvm-Remove-redhat-extensions-from-qmp-events.txt.patch +# For bz#1217351 - Overflow in malloc size calculation in VMDK driver +Patch1432: kvm-vmdk-Fix-overflow-if-l1_size-is-0x20000000.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1433: kvm-block-ssh-Drop-superfluous-libssh2_session_last_errn.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1434: kvm-block-ssh-Propagate-errors-through-check_host_key.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1435: kvm-block-ssh-Propagate-errors-through-authenticate.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1436: kvm-block-ssh-Propagate-errors-through-connect_to_ssh.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1437: kvm-block-ssh-Propagate-errors-to-open-and-create-method.patch +# For bz#1226683 - [virt-v2v] Backport upstream ssh driver to qemu-kvm +Patch1438: kvm-ssh-Don-t-crash-if-either-host-or-path-is-not-specif.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1439: kvm-curl-Replaced-old-error-handling-with-error-reportin.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1440: kvm-curl-Fix-long-line.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1441: kvm-curl-Remove-unnecessary-use-of-goto.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1442: kvm-curl-Fix-return-from-curl_read_cb-with-invalid-state.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1443: kvm-curl-Remove-erroneous-sleep-waiting-for-curl-complet.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1444: kvm-curl-Whitespace-only-changes.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1445: kvm-block-curl-Implement-the-libcurl-timer-callback-inte.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1446: kvm-curl-Remove-unnecessary-explicit-calls-to-internal-e.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1447: kvm-curl-Eliminate-unnecessary-use-of-curl_multi_socket_.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1448: kvm-curl-Ensure-all-informationals-are-checked-for-compl.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1449: kvm-curl-Fix-hang-reading-from-slow-connections.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1450: kvm-curl-Fix-build-when-curl_multi_socket_action-isn-t-a.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1451: kvm-curl-Remove-broken-parsing-of-options-from-url.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1452: kvm-curl-refuse-to-open-URL-from-HTTP-server-without-ran.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1453: kvm-curl-Add-sslverify-option.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1454: kvm-block-Drop-superfluous-conditionals-around-g_free.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1455: kvm-curl-Handle-failure-for-potentially-large-allocation.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1456: kvm-block.curl-adding-timeout-option.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1457: kvm-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1458: kvm-curl-The-macro-that-you-have-to-uncomment-to-get-deb.patch +# For bz#1226684 - [virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https +Patch1459: kvm-block-curl-Improve-type-safety-of-s-timeout.patch +# For bz#1185737 - qemu-kvm hang when boot with usb-host and sandbox was enabled +Patch1460: kvm-seccomp-add-timerfd_create-and-timerfd_settime-to-th.patch +# For bz#1226697 - [virt-v2v] Allow json: filenames in qemu-img +Patch1461: kvm-qdict-Add-qdict_join.patch +# For bz#1226697 - [virt-v2v] Allow json: filenames in qemu-img +Patch1462: kvm-block-Allow-JSON-filenames.patch +# For bz#1230808 - [abrt] qemu-system-x86: __memcmp_sse4_1(): qemu-system-x86_64 killed by SIGSEGV +Patch1463: kvm-spice-display-fix-segfault-in-qemu_spice_create_upda.patch +# For bz#1142857 - [abrt] qemu-kvm: bdrv_error_action(): qemu-kvm killed by SIGABRT +# For bz#1142857 - [abrt] qemu-kvm: bdrv_error_action(): qemu-kvm killed by SIGABRT +# For bz#(aka - +# For bz#8*10^6/7) - XFree86 apparently sets xhost to ill inital values +Patch1464: kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1465: kvm-qcow2-Put-cache-reference-in-error-case.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1466: kvm-qcow2-Catch-bdrv_getlength-error.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1467: kvm-block-Introduce-qemu_try_blockalign.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1468: kvm-qcow2-Catch-host_offset-for-data-allocation.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1469: kvm-iotests-Add-test-for-image-header-overlap.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1470: kvm-block-Catch-bs-drv-in-bdrv_check.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1471: kvm-qapi-block-Add-fatal-to-BLOCK_IMAGE_CORRUPTED.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1472: kvm-qcow2-Add-qcow2_signal_corruption.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1473: kvm-qcow2-Use-qcow2_signal_corruption-for-overlaps.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1474: kvm-qcow2-Check-L1-L2-reftable-entries-for-alignment.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1475: kvm-iotests-Add-more-tests-for-qcow2-corruption.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1476: kvm-qcow2-fix-leak-of-Qcow2DiscardRegion-in-update_refco.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1477: kvm-qcow2-Do-not-overflow-when-writing-an-L1-sector.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1478: kvm-iotests-Add-test-for-qcow2-L1-table-update.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1479: kvm-block-Add-qemu_-try_-blockalign0.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1480: kvm-qcow2-Calculate-refcount-block-entry-count.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1481: kvm-qcow2-Fix-leaks-in-dirty-images.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1482: kvm-qcow2-Split-qcow2_check_refcounts.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1483: kvm-qcow2-Use-sizeof-refcount_table.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1484: kvm-qcow2-Pull-check_refblocks-up.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1485: kvm-qcow2-Use-int64_t-for-in-memory-reftable-size.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1486: kvm-qcow2-Split-fail-code-in-L1-and-L2-checks.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1487: kvm-qcow2-Let-inc_refcounts-return-errno.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1488: kvm-qcow2-Let-inc_refcounts-resize-the-reftable.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1489: kvm-qcow2-Reuse-refcount-table-in-calculate_refcounts.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1490: kvm-qcow2-Fix-refcount-blocks-beyond-image-end.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1491: kvm-qcow2-Do-not-perform-potentially-damaging-repairs.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1492: kvm-qcow2-Rebuild-refcount-structure-during-check.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1493: kvm-qcow2-Clean-up-after-refcount-rebuild.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1494: kvm-iotests-Fix-test-outputs.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1495: kvm-iotests-Add-test-for-potentially-damaging-repairs.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1496: kvm-qcow2-Drop-REFCOUNT_SHIFT.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1497: kvm-block-Respect-underlying-file-s-EOF.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1498: kvm-qcow2-Fix-header-extension-size-check.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1499: kvm-qcow2.py-Add-required-padding-for-header-extensions.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1500: kvm-block-Don-t-probe-for-unknown-backing-file-format.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1501: kvm-qcow2-Add-two-more-unalignment-checks.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1502: kvm-iotests-Add-tests-for-more-corruption-cases.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1503: kvm-qcow2-Respect-new_block-in-alloc_refcount_block.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1504: kvm-iotests-Add-tests-for-refcount-table-growth.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1505: kvm-qcow2-Fix-header-update-with-overridden-backing-file.patch +# For bz#1129893 - Backport additional qcow2 corruption prevention and image repair patches +Patch1506: kvm-qcow2-Flush-pending-discards-before-allocating-clust.patch +# For bz#1229646 - CVE-2015-3214 qemu-kvm: qemu: i8254: out-of-bounds memory access in pit_ioport_read function [rhel-7.2] +Patch1507: kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1508: kvm-target-i386-fix-cpuid-leaf-0x0d.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1509: kvm-target-i386-Intel-MPX.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1510: kvm-always-update-the-MPX-model-specific-register.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1511: kvm-target-i386-bugfix-of-Intel-MPX.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1512: kvm-target-i386-fix-set-of-registers-zeroed-on-reset.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1513: kvm-target-i386-Add-mpx-CPU-feature-name.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1514: kvm-target-i386-Avoid-shifting-left-into-sign-bit.patch +# For bz#1233350 - [Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm +Patch1515: kvm-target-i386-add-Intel-AVX-512-support.patch +# For bz#1213881 - enable using tcmalloc for memory allocation in qemu-kvm +Patch1516: kvm-configure-Add-support-for-tcmalloc.patch +# For bz#1205100 - qemu-kvm: Qemu: PRDT overflow from guest to host [rhel-7.2] +Patch1517: kvm-ahci.c-mask-unused-flags-when-reading-size-PRDT-DBC.patch +# For bz#1205100 - qemu-kvm: Qemu: PRDT overflow from guest to host [rhel-7.2] +Patch1518: kvm-ide-Correct-handling-of-malformed-short-PRDTs.patch +# For bz#1243690 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.2] +Patch1519: kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch +# For bz#1243690 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.2] +Patch1520: kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch +# For bz#1243690 - EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.2] +Patch1521: kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch +# For bz#1235812 - block/curl: Fix generic "Input/output error" on failure +Patch1522: kvm-block-curl-Don-t-lose-original-error-when-a-connecti.patch +# For bz#1244347 - Quirk for Chelsio T5 MSI-X PBA +Patch1523: kvm-vfio-pci-Add-pba_offset-PCI-quirk-for-Chelsio-T5-dev.patch +# For bz#1238639 - qemu-img shows error message for backing file twice +Patch1524: kvm-block-Print-its-file-name-if-backing-file-opening-fa.patch +# For bz#1238639 - qemu-img shows error message for backing file twice +Patch1525: kvm-block-Propagate-error-in-bdrv_img_create.patch +# For bz#1238639 - qemu-img shows error message for backing file twice +Patch1526: kvm-iotests-Add-test-for-non-existing-backing-file.patch +# For bz#1243731 - smart card emulation doesn't work with USB3 (nec-xhci) controller +Patch1527: kvm-usb-ccid-add-missing-wakeup-calls.patch +# For bz#1217349 - qemu-img vpc driver segfault +Patch1528: kvm-vpc-Handle-failure-for-potentially-large-allocations.patch +# For bz#1217349 - qemu-img vpc driver segfault +Patch1529: kvm-block-vpc-prevent-overflow-if-max_table_entries-0x40.patch +# For bz#1217349 - qemu-img vpc driver segfault +Patch1530: kvm-block-qemu-iotests-add-check-for-multiplication-over.patch +# For bz#1249718 - Segfault occurred at Dst VM while completed migration upon ENOSPC +Patch1531: kvm-virtio-scsi-use-virtqueue_map_sg-when-loading-reques.patch +# For bz#1249718 - Segfault occurred at Dst VM while completed migration upon ENOSPC +Patch1532: kvm-scsi-disk-fix-cmd.mode-field-typo.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1533: kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1534: kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1535: kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1536: kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1537: kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1538: kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch +# For bz#1248766 - CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2] +Patch1539: kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch +# For bz#1171576 - test case 064 and 070 of qemu-iotests fail for vhdx with qemu-kvm-1.5.3-83.el7 +Patch1540: kvm-block-update-test-070-for-vhdx.patch +# For bz#1219217 - Coverity-detected defect: call to fcntl without checking return value +Patch1541: kvm-block-coverity-fix-check-return-value-for-fcntl-in-g.patch +# For bz#922014 - RFE: support hotplugging chardev & serial ports (Windows guests) +Patch1542: kvm-serial-reset-state-at-startup.patch +# For bz#1134670 - fail to specify the physical_block_size/logical_block_size value not 512 for IDE disk +Patch1543: kvm-ide-Check-validity-of-logical-block-size.patch +# For bz#1191226 - libvirt requires rtc-reset-reinjection command, backport it to RHEL7.1 +Patch1544: kvm-mc146818rtc-add-rtc-reset-reinjection-QMP-command.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1545: kvm-Drop-superfluous-conditionals-around-g_strdup.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1546: kvm-util-Drop-superfluous-conditionals-around-g_free.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1547: kvm-util-Fuse-g_malloc-memset-into-g_new0.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1548: kvm-util-uri-uri_new-can-t-fail-drop-dead-error-handling.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1549: kvm-util-uri-realloc2n-can-t-fail-drop-dead-error-handli.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1550: kvm-util-uri-URI-member-path-can-be-null-compare-more-ca.patch +# For bz#1218919 - Coverity-detected defect: buffer overrun at uri.c:2035 +Patch1551: kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch +# For bz#1170974 - test case 025 of qemu-iotests fail for raw with qemu-kvm-1.5.3-83.el7.x86_64 +Patch1552: kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch +# For bz#1270341 - qemu-kvm build failure race condition in tests/ide-test +Patch1553: kvm-qtest-ide-test-disable-flush-test.patch BuildRequires: zlib-devel @@ -2896,6 +3192,9 @@ BuildRequires: spice-server-devel >= 0.12.0 %if 0%{?have_seccomp:1} BuildRequires: libseccomp-devel >= 1.0.0 %endif +%if 0%{?have_tcmalloc:1} +BuildRequires: gperftools-devel +%endif # For network block driver BuildRequires: libcurl-devel %ifarch x86_64 @@ -2946,6 +3245,8 @@ BuildRequires: cpp # For compressed guest memory dumps BuildRequires: lzo-devel snappy-devel %endif +BuildRequires: libssh2-devel +BuildRequires: libcurl-devel %if 0%{!?build_only_sub:1} @@ -4481,6 +4782,151 @@ cp %{SOURCE18} pc-bios # keep "make check" happy %patch1406 -p1 %patch1407 -p1 %patch1408 -p1 +%patch1409 -p1 +%patch1410 -p1 +%patch1411 -p1 +%patch1412 -p1 +%patch1413 -p1 +%patch1414 -p1 +%patch1415 -p1 +%patch1416 -p1 +%patch1417 -p1 +%patch1418 -p1 +%patch1419 -p1 +%patch1420 -p1 +%patch1421 -p1 +%patch1422 -p1 +%patch1423 -p1 +%patch1424 -p1 +%patch1425 -p1 +%patch1426 -p1 +%patch1427 -p1 +%patch1428 -p1 +%patch1429 -p1 +%patch1430 -p1 +%patch1431 -p1 +%patch1432 -p1 +%patch1433 -p1 +%patch1434 -p1 +%patch1435 -p1 +%patch1436 -p1 +%patch1437 -p1 +%patch1438 -p1 +%patch1439 -p1 +%patch1440 -p1 +%patch1441 -p1 +%patch1442 -p1 +%patch1443 -p1 +%patch1444 -p1 +%patch1445 -p1 +%patch1446 -p1 +%patch1447 -p1 +%patch1448 -p1 +%patch1449 -p1 +%patch1450 -p1 +%patch1451 -p1 +%patch1452 -p1 +%patch1453 -p1 +%patch1454 -p1 +%patch1455 -p1 +%patch1456 -p1 +%patch1457 -p1 +%patch1458 -p1 +%patch1459 -p1 +%patch1460 -p1 +%patch1461 -p1 +%patch1462 -p1 +%patch1463 -p1 +%patch1464 -p1 +%patch1465 -p1 +%patch1466 -p1 +%patch1467 -p1 +%patch1468 -p1 +%patch1469 -p1 +%patch1470 -p1 +%patch1471 -p1 +%patch1472 -p1 +%patch1473 -p1 +%patch1474 -p1 +%patch1475 -p1 +%patch1476 -p1 +%patch1477 -p1 +%patch1478 -p1 +%patch1479 -p1 +%patch1480 -p1 +%patch1481 -p1 +%patch1482 -p1 +%patch1483 -p1 +%patch1484 -p1 +%patch1485 -p1 +%patch1486 -p1 +%patch1487 -p1 +%patch1488 -p1 +%patch1489 -p1 +%patch1490 -p1 +%patch1491 -p1 +%patch1492 -p1 +%patch1493 -p1 +%patch1494 -p1 +%patch1495 -p1 +%patch1496 -p1 +%patch1497 -p1 +%patch1498 -p1 +%patch1499 -p1 +%patch1500 -p1 +%patch1501 -p1 +%patch1502 -p1 +%patch1503 -p1 +%patch1504 -p1 +%patch1505 -p1 +%patch1506 -p1 +%patch1507 -p1 +%patch1508 -p1 +%patch1509 -p1 +%patch1510 -p1 +%patch1511 -p1 +%patch1512 -p1 +%patch1513 -p1 +%patch1514 -p1 +%patch1515 -p1 +%patch1516 -p1 +%patch1517 -p1 +%patch1518 -p1 +%patch1519 -p1 +%patch1520 -p1 +%patch1521 -p1 +%patch1522 -p1 +%patch1523 -p1 +%patch1524 -p1 +%patch1525 -p1 +%patch1526 -p1 +%patch1527 -p1 +%patch1528 -p1 +%patch1529 -p1 +%patch1530 -p1 +%patch1531 -p1 +%patch1532 -p1 +%patch1533 -p1 +%patch1534 -p1 +%patch1535 -p1 +%patch1536 -p1 +%patch1537 -p1 +%patch1538 -p1 +%patch1539 -p1 +%patch1540 -p1 +%patch1541 -p1 +%patch1542 -p1 +%patch1543 -p1 +%patch1544 -p1 +%patch1545 -p1 +%patch1546 -p1 +%patch1547 -p1 +%patch1548 -p1 +%patch1549 -p1 +%patch1550 -p1 +%patch1551 -p1 +%patch1552 -p1 +%patch1553 -p1 %build buildarch="%{kvm_target}-softmmu" @@ -4489,6 +4935,9 @@ buildarch="%{kvm_target}-softmmu" extraldflags="-Wl,--build-id"; buildldflags="VL_LDFLAGS=-Wl,--build-id" +# QEMU already knows how to set _FORTIFY_SOURCE +%global optflags %(echo %{optflags} | sed 's/-Wp,-D_FORTIFY_SOURCE=2//') + %ifarch s390 # drop -g flag to prevent memory exhaustion by linker %global optflags %(echo %{optflags} | sed 's/-g//') @@ -4528,7 +4977,8 @@ dobuild() { --disable-bluez \ --disable-vde \ --disable-curses \ - --disable-curl \ + --enable-curl \ + --enable-libssh2 \ --enable-vnc-tls \ --enable-vnc-sasl \ --enable-linux-aio \ @@ -4556,8 +5006,11 @@ dobuild() { --enable-rbd \ %endif --enable-glusterfs \ +%if 0%{?have_tcmalloc:1} + --enable-tcmalloc \ +%endif --block-drv-rw-whitelist=qcow2,raw,file,host_device,blkdebug,nbd,iscsi,gluster,rbd \ - --block-drv-ro-whitelist=vmdk,vhdx,vpc \ + --block-drv-ro-whitelist=vmdk,vhdx,vpc,ssh,https \ "$@" echo "config-host.mak contents:" @@ -4620,16 +5073,18 @@ dobuild --target-list="$buildarch" mkdir -p $RPM_BUILD_ROOT%{_bindir}/ mkdir -p $RPM_BUILD_ROOT%{_udevdir} + mkdir -p $RPM_BUILD_ROOT%{_datadir}/%{pkgname} install -m 0755 scripts/kvm/kvm_stat $RPM_BUILD_ROOT%{_bindir}/ install -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_udevdir} + install -m 0644 scripts/dump-guest-memory.py \ + $RPM_BUILD_ROOT%{_datadir}/%{pkgname} make DESTDIR=$RPM_BUILD_ROOT \ sharedir="%{_datadir}/%{pkgname}" \ datadir="%{_datadir}/%{pkgname}" \ install - mkdir -p $RPM_BUILD_ROOT%{_datadir}/%{pkgname} mkdir -p $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset # Install compatibility roms @@ -4657,7 +5112,7 @@ dobuild --target-list="$buildarch" install -m 0644 -t $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/tracetool/format scripts/tracetool/format/*.py mkdir -p $RPM_BUILD_ROOT%{qemudocdir} - install -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README README.systemtap COPYING COPYING.LIB LICENSE %{SOURCE19} + install -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README README.systemtap COPYING COPYING.LIB LICENSE %{SOURCE19} QMP/qmp-spec.txt QMP/qmp-events.txt mv ${RPM_BUILD_ROOT}%{_docdir}/qemu/qemu-doc.html $RPM_BUILD_ROOT%{qemudocdir} mv ${RPM_BUILD_ROOT}%{_docdir}/qemu/qemu-tech.html $RPM_BUILD_ROOT%{qemudocdir} mv ${RPM_BUILD_ROOT}%{_docdir}/qemu/qmp-commands.txt $RPM_BUILD_ROOT%{qemudocdir} @@ -4834,6 +5289,8 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %doc %{qemudocdir}/LICENSE %doc %{qemudocdir}/README.rhel6-gpxe-source %doc %{qemudocdir}/README.systemtap + %doc %{qemudocdir}/qmp-spec.txt + %doc %{qemudocdir}/qmp-events.txt %dir %{_datadir}/%{pkgname}/ %{_datadir}/%{pkgname}/keymaps/ %{_mandir}/man1/%{pkgname}.1* @@ -4893,6 +5350,7 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_datadir}/%{pkgname}/rhel6-rtl8139.rom %{_datadir}/%{pkgname}/rhel6-ne2k_pci.rom %{_datadir}/%{pkgname}/rhel6-e1000.rom + %{_datadir}/%{pkgname}/dump-guest-memory.py* %config(noreplace) %{_sysconfdir}/%{pkgname}/target-x86_64.conf %{?kvm_files:} %{?qemu_kvm_files:} @@ -4925,49 +5383,317 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %{_libdir}/pkgconfig/libcacard.pc %changelog -* Mon Oct 19 2015 Jeff E. Nelson - 1.5.3-86.el7_1.8 -- kvm-qtest-ide-test-disable-flush-test.patch [bz#1273098] -- Resolves: bz#1273098 +* Fri Oct 16 2015 Jeff E. Nelson - 1.5.3-105.el7 +- kvm-qtest-ide-test-disable-flush-test.patch [bz#1270341] +- Resolves: bz#1270341 (qemu-kvm build failure race condition in tests/ide-test) -* Fri Oct 09 2015 Miroslav Rezanina - 1.5.3-86.el7_1.7 -- kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch [bz#1205050] -- kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch [bz#1205050] -- Resolves: bz#1205050 - (CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.1.z]) - -* Thu Aug 06 2015 Miroslav Rezanina - 1.5.3-86.el7_1.6 -- kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch [bz#1248764] -- kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch [bz#1248764] -- kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch [bz#1248764] -- kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch [bz#1248764] -- kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch [bz#1248764] -- kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch [bz#1248764] -- kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch [bz#1248764] -- Resolves: bz#1248764 - (CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.1.z]) - -* Mon Jul 20 2015 Miroslav Rezanina - 1.5.3-86.el7_1.5 -- kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch [bz#1243726] -- Resolves: bz#1243726 - (CVE-2015-3214 qemu-kvm: qemu: i8254: out-of-bounds memory access in pit_ioport_read function [rhel-7.1.z]) - -* Fri Jul 17 2015 Miroslav Rezanina - 1.5.3-86.el7_1.4 -- kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch [bz#1243689] -- kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch [bz#1243689] -- kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch [bz#1243689] -- Resolves: bz#1243689 - (EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.1.z]) - -* Wed Jun 24 2015 Miroslav Rezanina - 1.5.3-86.el7_1.3 -- kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch [bz#1233643] -- Resolves: bz#1233643 +* Wed Sep 23 2015 Miroslav Rezanina - 1.5.3-104.el7 +- kvm-qemu-iotests-Filter-qemu-io-output-in-025.patch [bz#1170974] +- Resolves: bz#1170974 + (test case 025 of qemu-iotests fail for raw with qemu-kvm-1.5.3-83.el7.x86_64) + +* Thu Sep 10 2015 Miroslav Rezanina - 1.5.3-103.el7 +- kvm-Drop-superfluous-conditionals-around-g_strdup.patch [bz#1218919] +- kvm-util-Drop-superfluous-conditionals-around-g_free.patch [bz#1218919] +- kvm-util-Fuse-g_malloc-memset-into-g_new0.patch [bz#1218919] +- kvm-util-uri-uri_new-can-t-fail-drop-dead-error-handling.patch [bz#1218919] +- kvm-util-uri-realloc2n-can-t-fail-drop-dead-error-handli.patch [bz#1218919] +- kvm-util-uri-URI-member-path-can-be-null-compare-more-ca.patch [bz#1218919] +- kvm-util-uri-Add-overflow-check-to-rfc3986_parse_port.patch [bz#1218919] +- Resolves: bz#1218919 + (Coverity-detected defect: buffer overrun at uri.c:2035) + +* Thu Sep 03 2015 Miroslav Rezanina - 1.5.3-102.el7 +- kvm-mc146818rtc-add-rtc-reset-reinjection-QMP-command.patch [bz#1191226] +- Resolves: bz#1191226 + (libvirt requires rtc-reset-reinjection command, backport it to RHEL7.1) + +* Fri Aug 14 2015 Miroslav Rezanina - 1.5.3-101.el7 +- kvm-serial-reset-state-at-startup.patch [bz#922014] +- kvm-ide-Check-validity-of-logical-block-size.patch [bz#1134670] +- Resolves: bz#1134670 + (fail to specify the physical_block_size/logical_block_size value not 512 for IDE disk) +- Resolves: bz#922014 + (RFE: support hotplugging chardev & serial ports (Windows guests)) + +* Mon Aug 10 2015 Miroslav Rezanina - 1.5.3-100.el7 +- kvm-block-update-test-070-for-vhdx.patch [bz#1171576] +- kvm-block-coverity-fix-check-return-value-for-fcntl-in-g.patch [bz#1219217] +- Resolves: bz#1171576 + (test case 064 and 070 of qemu-iotests fail for vhdx with qemu-kvm-1.5.3-83.el7) +- Resolves: bz#1219217 + (Coverity-detected defect: call to fcntl without checking return value) + +* Thu Aug 06 2015 Miroslav Rezanina - 1.5.3-99.el7 +- kvm-usb-ccid-add-missing-wakeup-calls.patch [bz#1243731] +- kvm-vpc-Handle-failure-for-potentially-large-allocations.patch [bz#1217349] +- kvm-block-vpc-prevent-overflow-if-max_table_entries-0x40.patch [bz#1217349] +- kvm-block-qemu-iotests-add-check-for-multiplication-over.patch [bz#1217349] +- kvm-virtio-scsi-use-virtqueue_map_sg-when-loading-reques.patch [bz#1249718] +- kvm-scsi-disk-fix-cmd.mode-field-typo.patch [bz#1249718] +- kvm-rtl8139-avoid-nested-ifs-in-IP-header-parsing-CVE-20.patch [bz#1248766] +- kvm-rtl8139-drop-tautologous-if-ip-.-statement-CVE-2015-.patch [bz#1248766] +- kvm-rtl8139-skip-offload-on-short-Ethernet-IP-header-CVE.patch [bz#1248766] +- kvm-rtl8139-check-IP-Header-Length-field-CVE-2015-5165.patch [bz#1248766] +- kvm-rtl8139-check-IP-Total-Length-field-CVE-2015-5165.patch [bz#1248766] +- kvm-rtl8139-skip-offload-on-short-TCP-header-CVE-2015-51.patch [bz#1248766] +- kvm-rtl8139-check-TCP-Data-Offset-field-CVE-2015-5165.patch [bz#1248766] +- Resolves: bz#1217349 + (qemu-img vpc driver segfault) +- Resolves: bz#1243731 + (smart card emulation doesn't work with USB3 (nec-xhci) controller) +- Resolves: bz#1248766 + (CVE-2015-5165 qemu-kvm: Qemu: rtl8139 uninitialized heap memory information leakage to guest [rhel-7.2]) +- Resolves: bz#1249718 + (Segfault occurred at Dst VM while completed migration upon ENOSPC) + +* Fri Jul 24 2015 Miroslav Rezanina - 1.5.3-98.el7 +- kvm-block-curl-Don-t-lose-original-error-when-a-connecti.patch [bz#1235812] +- kvm-vfio-pci-Add-pba_offset-PCI-quirk-for-Chelsio-T5-dev.patch [bz#1244347] +- kvm-block-Print-its-file-name-if-backing-file-opening-fa.patch [bz#1238639] +- kvm-block-Propagate-error-in-bdrv_img_create.patch [bz#1238639] +- kvm-iotests-Add-test-for-non-existing-backing-file.patch [bz#1238639] +- Resolves: bz#1235812 + (block/curl: Fix generic "Input/output error" on failure) +- Resolves: bz#1238639 + (qemu-img shows error message for backing file twice) +- Resolves: bz#1244347 + (Quirk for Chelsio T5 MSI-X PBA) + +* Fri Jul 17 2015 Miroslav Rezanina - 1.5.3-97.el7 +- kvm-ide-Check-array-bounds-before-writing-to-io_buffer-C.patch [bz#1243690] +- kvm-ide-atapi-Fix-START-STOP-UNIT-command-completion.patch [bz#1243690] +- kvm-ide-Clear-DRQ-after-handling-all-expected-accesses.patch [bz#1243690] +- Resolves: bz#1243690 + (EMBARGOED CVE-2015-5154 qemu-kvm: qemu: ide: atapi: heap overflow during I/O buffer memory access [rhel-7.2]) + +* Thu Jul 16 2015 Miroslav Rezanina - 1.5.3-96.el7 +- kvm-ahci.c-mask-unused-flags-when-reading-size-PRDT-DBC.patch [bz#1205100] +- kvm-ide-Correct-handling-of-malformed-short-PRDTs.patch [bz#1205100] +- Resolves: bz#1205100 + (qemu-kvm: Qemu: PRDT overflow from guest to host [rhel-7.2]) + +* Tue Jul 07 2015 Miroslav Rezanina - 1.5.3-95.el7 +- kvm-i8254-fix-out-of-bounds-memory-access-in-pit_ioport_.patch [bz#1229646] +- kvm-target-i386-fix-cpuid-leaf-0x0d.patch [bz#1233350] +- kvm-target-i386-Intel-MPX.patch [bz#1233350] +- kvm-always-update-the-MPX-model-specific-register.patch [bz#1233350] +- kvm-target-i386-bugfix-of-Intel-MPX.patch [bz#1233350] +- kvm-target-i386-fix-set-of-registers-zeroed-on-reset.patch [bz#1233350] +- kvm-target-i386-Add-mpx-CPU-feature-name.patch [bz#1233350] +- kvm-target-i386-Avoid-shifting-left-into-sign-bit.patch [bz#1233350] +- kvm-target-i386-add-Intel-AVX-512-support.patch [bz#1233350] +- kvm-configure-Add-support-for-tcmalloc.patch [bz#1213881] +- Resolves: bz#1213881 + (enable using tcmalloc for memory allocation in qemu-kvm) +- Resolves: bz#1229646 + (CVE-2015-3214 qemu-kvm: qemu: i8254: out-of-bounds memory access in pit_ioport_read function [rhel-7.2]) +- Resolves: bz#1233350 + ([Intel 7.2 FEAT] Expose MPX feature to guest - qemu-kvm) + +* Fri Jun 26 2015 Miroslav Rezanina - 1.5.3-94.el7 +- kvm-qcow2-Put-cache-reference-in-error-case.patch [bz#1129893] +- kvm-qcow2-Catch-bdrv_getlength-error.patch [bz#1129893] +- kvm-block-Introduce-qemu_try_blockalign.patch [bz#1129893] +- kvm-qcow2-Catch-host_offset-for-data-allocation.patch [bz#1129893] +- kvm-iotests-Add-test-for-image-header-overlap.patch [bz#1129893] +- kvm-block-Catch-bs-drv-in-bdrv_check.patch [bz#1129893] +- kvm-qapi-block-Add-fatal-to-BLOCK_IMAGE_CORRUPTED.patch [bz#1129893] +- kvm-qcow2-Add-qcow2_signal_corruption.patch [bz#1129893] +- kvm-qcow2-Use-qcow2_signal_corruption-for-overlaps.patch [bz#1129893] +- kvm-qcow2-Check-L1-L2-reftable-entries-for-alignment.patch [bz#1129893] +- kvm-iotests-Add-more-tests-for-qcow2-corruption.patch [bz#1129893] +- kvm-qcow2-fix-leak-of-Qcow2DiscardRegion-in-update_refco.patch [bz#1129893] +- kvm-qcow2-Do-not-overflow-when-writing-an-L1-sector.patch [bz#1129893] +- kvm-iotests-Add-test-for-qcow2-L1-table-update.patch [bz#1129893] +- kvm-block-Add-qemu_-try_-blockalign0.patch [bz#1129893] +- kvm-qcow2-Calculate-refcount-block-entry-count.patch [bz#1129893] +- kvm-qcow2-Fix-leaks-in-dirty-images.patch [bz#1129893] +- kvm-qcow2-Split-qcow2_check_refcounts.patch [bz#1129893] +- kvm-qcow2-Use-sizeof-refcount_table.patch [bz#1129893] +- kvm-qcow2-Pull-check_refblocks-up.patch [bz#1129893] +- kvm-qcow2-Use-int64_t-for-in-memory-reftable-size.patch [bz#1129893] +- kvm-qcow2-Split-fail-code-in-L1-and-L2-checks.patch [bz#1129893] +- kvm-qcow2-Let-inc_refcounts-return-errno.patch [bz#1129893] +- kvm-qcow2-Let-inc_refcounts-resize-the-reftable.patch [bz#1129893] +- kvm-qcow2-Reuse-refcount-table-in-calculate_refcounts.patch [bz#1129893] +- kvm-qcow2-Fix-refcount-blocks-beyond-image-end.patch [bz#1129893] +- kvm-qcow2-Do-not-perform-potentially-damaging-repairs.patch [bz#1129893] +- kvm-qcow2-Rebuild-refcount-structure-during-check.patch [bz#1129893] +- kvm-qcow2-Clean-up-after-refcount-rebuild.patch [bz#1129893] +- kvm-iotests-Fix-test-outputs.patch [bz#1129893] +- kvm-iotests-Add-test-for-potentially-damaging-repairs.patch [bz#1129893] +- kvm-qcow2-Drop-REFCOUNT_SHIFT.patch [bz#1129893] +- kvm-block-Respect-underlying-file-s-EOF.patch [bz#1129893] +- kvm-qcow2-Fix-header-extension-size-check.patch [bz#1129893] +- kvm-qcow2.py-Add-required-padding-for-header-extensions.patch [bz#1129893] +- kvm-block-Don-t-probe-for-unknown-backing-file-format.patch [bz#1129893] +- kvm-qcow2-Add-two-more-unalignment-checks.patch [bz#1129893] +- kvm-iotests-Add-tests-for-more-corruption-cases.patch [bz#1129893] +- kvm-qcow2-Respect-new_block-in-alloc_refcount_block.patch [bz#1129893] +- kvm-iotests-Add-tests-for-refcount-table-growth.patch [bz#1129893] +- kvm-qcow2-Fix-header-update-with-overridden-backing-file.patch [bz#1129893] +- kvm-qcow2-Flush-pending-discards-before-allocating-clust.patch [bz#1129893] +- Resolves: bz#1129893 + (Backport additional qcow2 corruption prevention and image repair patches) + +* Wed Jun 24 2015 Miroslav Rezanina - 1.5.3-93.el7 +- kvm-atomics-add-explicit-compiler-fence-in-__atomic-memo.patch [bz#1142857 bz#1142857 (aka bz#8*bz#10^bz#6/bz#7)] +- Resolves: bz#1142857 ([abrt] qemu-kvm: bdrv_error_action(): qemu-kvm killed by SIGABRT) - -* Fri May 08 2015 Miroslav Rezanina - 1.5.3-86.el7_1.2 -- kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch [bz#1219269] -- Resolves: bz#1219269 - (EMBARGOED CVE-2015-3456 qemu-kvm: qemu: floppy disk controller flaw [rhel-7.1.z]) +- Resolves: bz#8*10^6/7) + (XFree86 apparently sets xhost to ill inital values) +- Resolves: bz#(aka + () + +* Tue Jun 16 2015 Miroslav Rezanina - 1.5.3-92.el7 +- kvm-seccomp-add-timerfd_create-and-timerfd_settime-to-th.patch [bz#1185737] +- kvm-qdict-Add-qdict_join.patch [bz#1226697] +- kvm-block-Allow-JSON-filenames.patch [bz#1226697] +- kvm-spice-display-fix-segfault-in-qemu_spice_create_upda.patch [bz#1230808] +- Resolves: bz#1185737 + (qemu-kvm hang when boot with usb-host and sandbox was enabled) +- Resolves: bz#1226697 + ([virt-v2v] Allow json: filenames in qemu-img) +- Resolves: bz#1230808 + ([abrt] qemu-system-x86: __memcmp_sse4_1(): qemu-system-x86_64 killed by SIGSEGV) + +* Mon Jun 15 2015 Miroslav Rezanina - 1.5.3-91.el7 +- kvm-vmdk-Fix-overflow-if-l1_size-is-0x20000000.patch [bz#1217351] +- kvm-block-ssh-Drop-superfluous-libssh2_session_last_errn.patch [bz#1226683] +- kvm-block-ssh-Propagate-errors-through-check_host_key.patch [bz#1226683] +- kvm-block-ssh-Propagate-errors-through-authenticate.patch [bz#1226683] +- kvm-block-ssh-Propagate-errors-through-connect_to_ssh.patch [bz#1226683] +- kvm-block-ssh-Propagate-errors-to-open-and-create-method.patch [bz#1226683] +- kvm-ssh-Don-t-crash-if-either-host-or-path-is-not-specif.patch [bz#1226683] +- kvm-curl-Replaced-old-error-handling-with-error-reportin.patch [bz#1226684] +- kvm-curl-Fix-long-line.patch [bz#1226684] +- kvm-curl-Remove-unnecessary-use-of-goto.patch [bz#1226684] +- kvm-curl-Fix-return-from-curl_read_cb-with-invalid-state.patch [bz#1226684] +- kvm-curl-Remove-erroneous-sleep-waiting-for-curl-complet.patch [bz#1226684] +- kvm-curl-Whitespace-only-changes.patch [bz#1226684] +- kvm-block-curl-Implement-the-libcurl-timer-callback-inte.patch [bz#1226684] +- kvm-curl-Remove-unnecessary-explicit-calls-to-internal-e.patch [bz#1226684] +- kvm-curl-Eliminate-unnecessary-use-of-curl_multi_socket_.patch [bz#1226684] +- kvm-curl-Ensure-all-informationals-are-checked-for-compl.patch [bz#1226684] +- kvm-curl-Fix-hang-reading-from-slow-connections.patch [bz#1226684] +- kvm-curl-Fix-build-when-curl_multi_socket_action-isn-t-a.patch [bz#1226684] +- kvm-curl-Remove-broken-parsing-of-options-from-url.patch [bz#1226684] +- kvm-curl-refuse-to-open-URL-from-HTTP-server-without-ran.patch [bz#1226684] +- kvm-curl-Add-sslverify-option.patch [bz#1226684] +- kvm-block-Drop-superfluous-conditionals-around-g_free.patch [bz#1226684] +- kvm-curl-Handle-failure-for-potentially-large-allocation.patch [bz#1226684] +- kvm-block.curl-adding-timeout-option.patch [bz#1226684] +- kvm-curl-Allow-a-cookie-or-cookies-to-be-sent-with-http-.patch [bz#1226684] +- kvm-curl-The-macro-that-you-have-to-uncomment-to-get-deb.patch [bz#1226684] +- kvm-block-curl-Improve-type-safety-of-s-timeout.patch [bz#1226684] +- kvm-Enable-ssh-driver-read-only.patch [bz#1226683] +- kvm-Enable-curl-driver-read-only.patch [bz#1226684] +- Resolves: bz#1217351 + (Overflow in malloc size calculation in VMDK driver) +- Resolves: bz#1226683 + ([virt-v2v] Backport upstream ssh driver to qemu-kvm) +- Resolves: bz#1226684 + ([virt-v2v] Enable curl driver + upstream features + fixes in qemu-kvm and enable https) + +* Thu Jun 04 2015 Miroslav Rezanina - 1.5.3-90.el7 +- kvm-qcow2-Pass-discard-type-to-qcow2_discard_clusters.patch [bz#1208808] +- kvm-qcow2-Discard-VM-state-in-active-L1-after-creating-s.patch [bz#1208808] +- kvm-configure-Require-libfdt-for-arm-ppc-microblaze-soft.patch [bz#1217850] +- kvm-configure-Add-handling-code-for-AArch64-targets.patch [bz#1217850] +- kvm-configure-permit-compilation-on-arm-aarch64.patch [bz#1217850] +- kvm-spec-Allow-build-on-aarch64.patch [bz#1217850] +- kvm-Remove-redhat-extensions-from-qmp-events.txt.patch [bz#1222833] +- kvm-spec-Add-misssing-QMP-documentation-files.patch [bz#1222833] +- Resolves: bz#1208808 + (creating second and further snapshot takes ages) +- Resolves: bz#1217850 + (qemu-kvm: Enable build on aarch64) +- Resolves: bz#1222833 + (We ship incomplete QMP documentation) + +* Wed May 27 2015 Miroslav Rezanina - 1.5.3-89.el7 +- kvm-CVE-2015-1779-incrementally-decode-websocket-frames.patch [bz#1206497] +- kvm-CVE-2015-1779-limit-size-of-HTTP-headers-from-websoc.patch [bz#1206497] +- kvm-qemu-iotests-Test-unaligned-4k-zero-write.patch [bz#1200295] +- kvm-block-Fix-NULL-deference-for-unaligned-write-if-qiov.patch [bz#1200295] +- kvm-qemu-iotests-Test-unaligned-sub-block-zero-write.patch [bz#1200295] +- kvm-fdc-force-the-fifo-access-to-be-in-bounds-of-the-all.patch [bz#1219270] +- Resolves: bz#1200295 + (QEMU segfault when doing unaligned zero write to non-512 disk) +- Resolves: bz#1206497 + (CVE-2015-1779 qemu-kvm: qemu: vnc: insufficient resource limiting in VNC websockets decoder [rhel-7.2]) +- Resolves: bz#1219270 + (CVE-2015-3456 qemu-kvm: qemu: floppy disk controller flaw [rhel-7.2]) + +* Wed May 06 2015 Miroslav Rezanina - 1.5.3-88.el7 +- kvm-vfio-warn-if-host-device-rom-can-t-be-read.patch [bz#1210503] +- kvm-vfio-Do-not-reattempt-a-failed-rom-read.patch [bz#1210503] +- kvm-vfio-Correction-in-vfio_rom_read-when-attempting-rom.patch [bz#1210503] +- kvm-vfio-Fix-overrun-after-readlink-fills-buffer-complet.patch [bz#1210504] +- kvm-vfio-use-correct-runstate.patch [bz#1210505] +- kvm-vfio-pci-Fix-BAR-size-overflow.patch [bz#1181267] +- kvm-vfio-Use-vfio-type1-v2-IOMMU-interface.patch [bz#1210508] +- kvm-vfio-pci-Enable-device-request-notification-support.patch [bz#1210509] +- kvm-vfio-pci-Further-fix-BAR-size-overflow.patch [bz#1181267] +- kvm-vfio-pci-Fix-error-path-sign.patch [bz#1210504] +- kvm-x86-Use-common-variable-range-MTRR-counts.patch [bz#1210510] +- kvm-x86-kvm-Add-MTRR-support-for-kvm_get-put_msrs.patch [bz#1210510] +- kvm-x86-Clear-MTRRs-on-vCPU-reset.patch [bz#1210510] +- kvm-spec-Exclude-aarch64.patch [bz#1217850] +- Resolves: bz#1181267 + (vfio-pci: Fix BAR size overflow) +- Resolves: bz#1210503 + (vfio improve PCI ROM loading error handling) +- Resolves: bz#1210504 + (vfio: Fix overrun after readlink() fills buffer completely) +- Resolves: bz#1210505 + (vfio: use correct runstate) +- Resolves: bz#1210508 + (vfio: Use vfio type1 v2 IOMMU interface) +- Resolves: bz#1210509 + (vfio-pci: Enable device request notification support) +- Resolves: bz#1210510 + (Sync MTRRs with KVM and disable on reset) +- Resolves: bz#1217850 + (qemu-kvm: ExcludeArch: aarch64) + +* Tue Mar 17 2015 Miroslav Rezanina - 1.5.3-87.el7 +- kvm-trace-add-qemu_system_powerdown_request-and-qemu_sys.patch [bz#1155671] +- kvm-virtio-net-drop-assert-on-vm-stop.patch [bz#1139562] +- kvm-socket-shutdown.patch [bz#1086168] +- kvm-Handle-bi-directional-communication-for-fd-migration.patch [bz#1086168] +- kvm-migration_cancel-shutdown-migration-socket.patch [bz#1086168] +- kvm-iscsi-Refuse-to-open-as-writable-if-the-LUN-is-write.patch [bz#1032412] +- kvm-main-set-current_machine-before-calling-machine-init.patch [bz#1176283] +- kvm-pc_sysfw-prevent-pflash-and-or-mis-sized-firmware-fo.patch [bz#1176283] +- kvm-Restore-atapi_dma-flag-across-migration.patch [bz#892258] +- kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch [bz#892258] +- kvm-build-reenable-local-builds-to-pass-enable-debug-RHE.patch [] +- kvm-raw-posix-Fail-gracefully-if-no-working-alignment-is.patch [bz#1184363] +- kvm-block-Add-Error-argument-to-bdrv_refresh_limits.patch [bz#1184363] +- kvm-Python-lang-gdb-script-to-extract-x86_64-guest-vmcor.patch [bz#828493] +- kvm-RPM-spec-install-dump-guest-memory.py-RHEL-only.patch [bz#828493] +- kvm-spec-Enable-build-of-qemu-img-and-libcacard-for-ppc6.patch [bz#1190086] +- Resolves: bz#1032412 + (opening read-only iscsi lun as read-write should fail) +- Resolves: bz#1086168 + (qemu-kvm can not cancel migration in src host when network of dst host failed) +- Resolves: bz#1139562 + (qemu-kvm with vhost=off and sndbuf=100 crashed when stop it during pktgen test from guest to host) +- Resolves: bz#1155671 + ([Fujitsu 7.2 FEAT]: QEMU: Add tracepoints in system shutdown) +- Resolves: bz#1176283 + ([migration]migration failed when configure guest with OVMF bios + machine type=rhel6.5.0) +- Resolves: bz#1184363 + (Qemu process fails to start with a multipath device with all paths failed) +- Resolves: bz#1190086 + (build qemu-img/libcacard on ppc64le for 7.2) +- Resolves: bz#828493 + ([Hitachi 7.2 FEAT] Extract guest memory dump from qemu-kvm core) +- Resolves: bz#892258 + (ide CDROM io/data errors after migration) * Thu Mar 05 2015 Miroslav Rezanina - 1.5.3-86.el7_1.1 - kvm-pc-add-rhel6.6.0-machine-type.patch [bz#1198958]