From 218e998aa8bf263cd8a53bd742d03162c780aa7a Mon Sep 17 00:00:00 2001 From: CentOS Buildsys Date: Nov 11 2013 07:53:41 +0000 Subject: import qemu-kvm-1.5.3-19.el7.src.rpm --- diff --git a/.qemu-kvm.metadata b/.qemu-kvm.metadata new file mode 100644 index 0000000..5ed19e0 --- /dev/null +++ b/.qemu-kvm.metadata @@ -0,0 +1,5 @@ +faac4c56f0ef593721edc66af965bac63760965b SOURCES/rhel6-ne2k_pci.rom +ca79836ccce0ffbf25aac4687a3aa64bf281a3c1 SOURCES/rhel6-rtl8139.rom +82eda3fb78a792745e46bcbbea8290cc444ae6bf SOURCES/rhel6-virtio.rom +f5ddbc9701698bc4adc5e98c63ad438c3b8e8510 SOURCES/rhel6-pcnet.rom +e5a40bb63de8445a465c507ce27e736cff35ec12 SOURCES/qemu-1.5.3.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch b/SOURCES/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch new file mode 100644 index 0000000..69f1ec6 --- /dev/null +++ b/SOURCES/0000-libcacard-fix-missing-symbols-in-libcacard.so.patch @@ -0,0 +1,22 @@ +From 9cb057a4d615ea4773066eac44fe8e88414fac4b Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Mon, 4 Mar 2013 09:43:01 +0100 +Subject: libcacard: fix missing symbols in libcacard.so + +Message-Id: <94afb78477a5b078449e5d48b38e74aac3fa5ac4.1354903384.git.crobinso@redhat.com> + +Signed-off-by: Alon Levy + +diff --git a/libcacard/Makefile b/libcacard/Makefile +index 47827a0..6bdf0c4 100644 +--- a/libcacard/Makefile ++++ b/libcacard/Makefile +@@ -4,7 +4,7 @@ TOOLS += vscclient$(EXESUF) + + # objects linked into a shared library, built with libtool with -fPIC if required + libcacard-obj-y = $(stub-obj-y) $(libcacard-y) +-libcacard-obj-y += util/osdep.o util/cutils.o util/qemu-timer-common.o util/error.o ++libcacard-obj-y += util/osdep.o util/iov.o util/cutils.o util/qemu-timer-common.o util/error.o util/hexdump.o + libcacard-obj-$(CONFIG_WIN32) += util/oslib-win32.o util/qemu-thread-win32.o + libcacard-obj-$(CONFIG_POSIX) += util/oslib-posix.o util/qemu-thread-posix.o + libcacard-obj-y += $(filter trace/%, $(util-obj-y)) diff --git a/SOURCES/80-kvm.rules b/SOURCES/80-kvm.rules new file mode 100644 index 0000000..e61b48f --- /dev/null +++ b/SOURCES/80-kvm.rules @@ -0,0 +1 @@ +KERNEL=="kvm", GROUP="kvm", MODE="0666" diff --git a/SOURCES/99-qemu-guest-agent.rules b/SOURCES/99-qemu-guest-agent.rules new file mode 100644 index 0000000..8a290ab --- /dev/null +++ b/SOURCES/99-qemu-guest-agent.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \ + TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service" diff --git a/SOURCES/block-add-block-driver-read-only-whitelist.patch b/SOURCES/block-add-block-driver-read-only-whitelist.patch new file mode 100644 index 0000000..12ea638 --- /dev/null +++ b/SOURCES/block-add-block-driver-read-only-whitelist.patch @@ -0,0 +1,284 @@ +From e04d52892c7fcd0e2ec70f77f3e5b934d45918c8 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 09:56:17 +0200 +Subject: block: add block driver read only whitelist + +Message-id: <6873f36f1d3c26ad7b84bf2150c0a98afd6c5e72.1375208619.git.mrezanin@redhat.com> +Patchwork-id: 52827 +O-Subject: [RHEL7 qemu-kvm PATCH 4.5/5] block: add block driver read only whitelist +Bugzilla: 836675 +RH-Acked-by: Fam Zheng +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Fam Zheng + +This is missing patch required for "VMDK Backports and Spec Update" serie. + +We may want to include a driver in the whitelist for read only tasks +such as diagnosing or exporting guest data (with libguestfs as a good +example). This patch introduces a readonly whitelist option, and for +backward compatibility, the old configure option --block-drv-whitelist +is now an alias to rw whitelist. + +Drivers in readonly list is only permitted to open file readonly, and +returns -ENOTSUP for RW opening. + +E.g. To include vmdk readonly, and others read+write: + ./configure --target-list=x86_64-softmmu \ + --block-drv-rw-whitelist=qcow2,raw,file,qed \ + --block-drv-ro-whitelist=vmdk + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit b64ec4e4ade581d662753cdeb0d7e0e27aafbf81) + +Signed-off-by: Miroslav Rezanina + +diff --git a/block.c b/block.c +index 3f87489..65c0b60 100644 +--- a/block.c ++++ b/block.c +@@ -328,28 +328,40 @@ BlockDriver *bdrv_find_format(const char *format_name) + return NULL; + } + +-static int bdrv_is_whitelisted(BlockDriver *drv) ++static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only) + { +- static const char *whitelist[] = { +- CONFIG_BDRV_WHITELIST ++ static const char *whitelist_rw[] = { ++ CONFIG_BDRV_RW_WHITELIST ++ }; ++ static const char *whitelist_ro[] = { ++ CONFIG_BDRV_RO_WHITELIST + }; + const char **p; + +- if (!whitelist[0]) ++ if (!whitelist_rw[0] && !whitelist_ro[0]) { + return 1; /* no whitelist, anything goes */ ++ } + +- for (p = whitelist; *p; p++) { ++ for (p = whitelist_rw; *p; p++) { + if (!strcmp(drv->format_name, *p)) { + return 1; + } + } ++ if (read_only) { ++ for (p = whitelist_ro; *p; p++) { ++ if (!strcmp(drv->format_name, *p)) { ++ return 1; ++ } ++ } ++ } + return 0; + } + +-BlockDriver *bdrv_find_whitelisted_format(const char *format_name) ++BlockDriver *bdrv_find_whitelisted_format(const char *format_name, ++ bool read_only) + { + BlockDriver *drv = bdrv_find_format(format_name); +- return drv && bdrv_is_whitelisted(drv) ? drv : NULL; ++ return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL; + } + + typedef struct CreateCo { +@@ -684,10 +696,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + + trace_bdrv_open_common(bs, filename ?: "", flags, drv->format_name); + +- if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { +- return -ENOTSUP; +- } +- + /* bdrv_open() with directly using a protocol as drv. This layer is already + * opened, so assign it to bs (while file becomes a closed BlockDriverState) + * and return immediately. */ +@@ -698,9 +706,15 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + + bs->open_flags = flags; + bs->buffer_alignment = 512; ++ open_flags = bdrv_open_flags(bs, flags); ++ bs->read_only = !(open_flags & BDRV_O_RDWR); ++ ++ if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) { ++ return -ENOTSUP; ++ } + + assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ +- if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) { ++ if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) { + bdrv_enable_copy_on_read(bs); + } + +@@ -714,9 +728,6 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + bs->opaque = g_malloc0(drv->instance_size); + + bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB); +- open_flags = bdrv_open_flags(bs, flags); +- +- bs->read_only = !(open_flags & BDRV_O_RDWR); + + /* Open the image, either directly or using a protocol */ + if (drv->bdrv_file_open) { +@@ -801,7 +812,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + /* Find the right block driver */ + drvname = qdict_get_try_str(options, "driver"); + if (drvname) { +- drv = bdrv_find_whitelisted_format(drvname); ++ drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); + qdict_del(options, "driver"); + } else if (filename) { + drv = bdrv_find_protocol(filename); +diff --git a/blockdev.c b/blockdev.c +index 625d041..6500c47 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -477,7 +477,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + error_printf("\n"); + return NULL; + } +- drv = bdrv_find_whitelisted_format(buf); ++ drv = bdrv_find_whitelisted_format(buf, ro); + if (!drv) { + error_report("'%s' invalid format", buf); + return NULL; +@@ -1024,7 +1024,7 @@ void qmp_change_blockdev(const char *device, const char *filename, + } + + if (format) { +- drv = bdrv_find_whitelisted_format(format); ++ drv = bdrv_find_whitelisted_format(format, bs->read_only); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); + return; +diff --git a/configure b/configure +index eb74510..a71e8a1 100755 +--- a/configure ++++ b/configure +@@ -123,7 +123,8 @@ interp_prefix="/usr/gnemul/qemu-%M" + static="no" + cross_prefix="" + audio_drv_list="" +-block_drv_whitelist="" ++block_drv_rw_whitelist="" ++block_drv_ro_whitelist="" + host_cc="cc" + libs_softmmu="" + libs_tools="" +@@ -708,7 +709,9 @@ for opt do + ;; + --audio-drv-list=*) audio_drv_list="$optarg" + ;; +- --block-drv-whitelist=*) block_drv_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` ++ --block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` ++ ;; ++ --block-drv-ro-whitelist=*) block_drv_ro_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` + ;; + --enable-debug-tcg) debug_tcg="yes" + ;; +@@ -1105,7 +1108,12 @@ echo " --disable-cocoa disable Cocoa (Mac OS X only)" + echo " --enable-cocoa enable Cocoa (default on Mac OS X)" + echo " --audio-drv-list=LIST set audio drivers list:" + echo " Available drivers: $audio_possible_drivers" +-echo " --block-drv-whitelist=L set block driver whitelist" ++echo " --block-drv-whitelist=L Same as --block-drv-rw-whitelist=L" ++echo " --block-drv-rw-whitelist=L" ++echo " set block driver read-write whitelist" ++echo " (affects only QEMU, not qemu-img)" ++echo " --block-drv-ro-whitelist=L" ++echo " set block driver read-only whitelist" + echo " (affects only QEMU, not qemu-img)" + echo " --enable-mixemu enable mixer emulation" + echo " --disable-xen disable xen backend driver support" +@@ -3525,7 +3533,8 @@ echo "curses support $curses" + echo "curl support $curl" + echo "mingw32 support $mingw32" + echo "Audio drivers $audio_drv_list" +-echo "Block whitelist $block_drv_whitelist" ++echo "Block whitelist (rw) $block_drv_rw_whitelist" ++echo "Block whitelist (ro) $block_drv_ro_whitelist" + echo "Mixer emulation $mixemu" + echo "VirtFS support $virtfs" + echo "VNC support $vnc" +@@ -3704,7 +3713,8 @@ fi + if test "$audio_win_int" = "yes" ; then + echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak + fi +-echo "CONFIG_BDRV_WHITELIST=$block_drv_whitelist" >> $config_host_mak ++echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak ++echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak + if test "$mixemu" = "yes" ; then + echo "CONFIG_MIXEMU=y" >> $config_host_mak + fi +diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c +index 0ac65d4..247f32f 100644 +--- a/hw/block/xen_disk.c ++++ b/hw/block/xen_disk.c +@@ -780,11 +780,13 @@ static int blk_connect(struct XenDevice *xendev) + { + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int pers, index, qflags; ++ bool readonly = true; + + /* read-only ? */ + qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO; + if (strcmp(blkdev->mode, "w") == 0) { + qflags |= BDRV_O_RDWR; ++ readonly = false; + } + + /* init qemu block driver */ +@@ -795,8 +797,10 @@ static int blk_connect(struct XenDevice *xendev) + xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n"); + blkdev->bs = bdrv_new(blkdev->dev); + if (blkdev->bs) { +- if (bdrv_open(blkdev->bs, blkdev->filename, NULL, qflags, +- bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) { ++ BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto, ++ readonly); ++ if (bdrv_open(blkdev->bs, ++ blkdev->filename, NULL, qflags, drv) != 0) { + bdrv_delete(blkdev->bs); + blkdev->bs = NULL; + } +diff --git a/include/block/block.h b/include/block/block.h +index 1251c5c..5604418 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -124,7 +124,8 @@ void bdrv_init(void); + void bdrv_init_with_whitelist(void); + BlockDriver *bdrv_find_protocol(const char *filename); + BlockDriver *bdrv_find_format(const char *format_name); +-BlockDriver *bdrv_find_whitelisted_format(const char *format_name); ++BlockDriver *bdrv_find_whitelisted_format(const char *format_name, ++ bool readonly); + int bdrv_create(BlockDriver *drv, const char* filename, + QEMUOptionParameter *options); + int bdrv_create_file(const char* filename, QEMUOptionParameter *options); +diff --git a/scripts/create_config b/scripts/create_config +index c471e8c..258513a 100755 +--- a/scripts/create_config ++++ b/scripts/create_config +@@ -34,8 +34,15 @@ case $line in + done + echo "" + ;; +- CONFIG_BDRV_WHITELIST=*) +- echo "#define CONFIG_BDRV_WHITELIST \\" ++ CONFIG_BDRV_RW_WHITELIST=*) ++ echo "#define CONFIG_BDRV_RW_WHITELIST\\" ++ for drv in ${line#*=}; do ++ echo " \"${drv}\",\\" ++ done ++ echo " NULL" ++ ;; ++ CONFIG_BDRV_RO_WHITELIST=*) ++ echo "#define CONFIG_BDRV_RO_WHITELIST\\" + for drv in ${line#*=}; do + echo " \"${drv}\",\\" + done diff --git a/SOURCES/bridge.conf b/SOURCES/bridge.conf new file mode 100644 index 0000000..a573665 --- /dev/null +++ b/SOURCES/bridge.conf @@ -0,0 +1 @@ +allow virbr0 diff --git a/SOURCES/change-path-from-qemu-to-qemu-kvm.patch b/SOURCES/change-path-from-qemu-to-qemu-kvm.patch new file mode 100644 index 0000000..4c0b87f --- /dev/null +++ b/SOURCES/change-path-from-qemu-to-qemu-kvm.patch @@ -0,0 +1,37 @@ +From 27267616896168fe1177c42a73246a8a9c551be3 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 11 Apr 2013 11:07:31 +0200 +Subject: Change qemu to qemu-kvm + +We use qemu-kvm as name for RHEL 7. This patch fixes various pathes and files that uses qemu so they use qemu-kvm instead. + +Signed-off-by: Miroslav Rezanina + +diff --git a/os-posix.c b/os-posix.c +index d39261d..3a4678a 100644 +--- a/os-posix.c ++++ b/os-posix.c +@@ -82,7 +82,7 @@ void os_setup_signal_handling(void) + /* Find a likely location for support files using the location of the binary. + For installed binaries this will be "$bindir/../share/qemu". When + running from the build tree this will be "$bindir/../pc-bios". */ +-#define SHARE_SUFFIX "/share/qemu" ++#define SHARE_SUFFIX "/share/qemu-kvm" + #define BUILD_SUFFIX "/pc-bios" + char *os_find_datadir(const char *argv0) + { +diff --git a/redhat/qemu-kvm.spec.template b/redhat/qemu-kvm.spec.template +index 84088eb..646eb1a 100644 +diff --git a/ui/vnc.c b/ui/vnc.c +index dfc7459..3726352 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -3260,7 +3260,7 @@ void vnc_display_open(DisplayState *ds, const char *display, Error **errp) + } + + #ifdef CONFIG_VNC_SASL +- if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { ++ if ((saslErr = sasl_server_init(NULL, "qemu-kvm")) != SASL_OK) { + error_setg(errp, "Failed to initialize SASL auth: %s", + sasl_errstring(saslErr, NULL, NULL)); + goto fail; diff --git a/SOURCES/disable-hpet-device.patch b/SOURCES/disable-hpet-device.patch new file mode 100644 index 0000000..87a79bb --- /dev/null +++ b/SOURCES/disable-hpet-device.patch @@ -0,0 +1,35 @@ +From 94ee0c3faaaf6a225f605e00ff623ba9792cedfc Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 22 May 2013 12:23:00 +0200 +Subject: Disable HPET device + +Bugzilla: 947441 + +We do not support HPET, disabling it. + +Signed-off-by: Miroslav Rezanina + +diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak +index fb6caaf..cf6ee9f 100644 +--- a/default-configs/i386-softmmu.mak ++++ b/default-configs/i386-softmmu.mak +@@ -21,7 +21,6 @@ CONFIG_I8257=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y + CONFIG_PIIX_PCI=y +-CONFIG_HPET=y + CONFIG_I8259=y + CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index 69cdda0..4234f00 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -21,7 +21,6 @@ CONFIG_I8257=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y + CONFIG_PIIX_PCI=y +-CONFIG_HPET=y + CONFIG_I8259=y + CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) diff --git a/SOURCES/disable-unsupported-audio-devices.patch b/SOURCES/disable-unsupported-audio-devices.patch new file mode 100644 index 0000000..e56c567 --- /dev/null +++ b/SOURCES/disable-unsupported-audio-devices.patch @@ -0,0 +1,32 @@ +From be17223dfe2b717322f878fbfa9e354be73f1569 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Tue, 19 Mar 2013 07:37:43 -0400 +Subject: Disable unsupported audio devices + +Bugzilla: 921974 + +Only AC97 and Intel HDA are supported audio devices. Limit build only to these devices. + +Signed-off-by: Miroslav Rezanina + +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index 87334a4..a5dee5d 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -10,7 +10,6 @@ CONFIG_PCNET_PCI=y + CONFIG_PCNET_COMMON=y + CONFIG_AC97=y + CONFIG_HDA=y +-CONFIG_ES1370=y + CONFIG_RTL8139_PCI=y + CONFIG_E1000_PCI=y + CONFIG_VMXNET3_PCI=y +diff --git a/default-configs/sound.mak b/default-configs/sound.mak +index 4f22c34..e69de29 100644 +--- a/default-configs/sound.mak ++++ b/default-configs/sound.mak +@@ -1,4 +0,0 @@ +-CONFIG_SB16=y +-CONFIG_ADLIB=y +-CONFIG_GUS=y +-CONFIG_CS4231A=y diff --git a/SOURCES/disable-unsupported-emulated-network-devices.patch b/SOURCES/disable-unsupported-emulated-network-devices.patch new file mode 100644 index 0000000..5689194 --- /dev/null +++ b/SOURCES/disable-unsupported-emulated-network-devices.patch @@ -0,0 +1,155 @@ +From 79b7ddc06f610199104fbb77fded7ed250056624 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 22 May 2013 11:59:23 +0200 +Subject: Disable unsupported emulated network devices + +Bugzilla: 921974 + +Disable following network devices as they are not supported: +- ne2k_isa +- ne2k_pci +- pcnet +- vmxnet3 + +Signed-off-by: Miroslav Rezanina + +diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak +index b208e10..fb6caaf 100644 +--- a/default-configs/i386-softmmu.mak ++++ b/default-configs/i386-softmmu.mak +@@ -20,7 +20,6 @@ CONFIG_APM=y + CONFIG_I8257=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y +-CONFIG_NE2000_ISA=y + CONFIG_PIIX_PCI=y + CONFIG_HPET=y + CONFIG_I8259=y +diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak +index 4fed1ca..3c5fb43 100644 +--- a/default-configs/mips-softmmu.mak ++++ b/default-configs/mips-softmmu.mak +@@ -22,7 +22,6 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y +-CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak +index 5e4e758..c05d44a 100644 +--- a/default-configs/mips64-softmmu.mak ++++ b/default-configs/mips64-softmmu.mak +@@ -22,7 +22,6 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y +-CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak +index cc54619..40aaea5 100644 +--- a/default-configs/mips64el-softmmu.mak ++++ b/default-configs/mips64el-softmmu.mak +@@ -23,7 +23,6 @@ CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y + CONFIG_IDE_VIA=y +-CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak +index 1e59e68..ca44d0e 100644 +--- a/default-configs/mipsel-softmmu.mak ++++ b/default-configs/mipsel-softmmu.mak +@@ -22,7 +22,6 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y +-CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index a5dee5d..c0fb0ae 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -4,15 +4,11 @@ CONFIG_VIRTIO=y + CONFIG_USB_UHCI=y + CONFIG_USB_EHCI=y + CONFIG_USB_XHCI=y +-CONFIG_NE2000_PCI=y + CONFIG_EEPRO100_PCI=y +-CONFIG_PCNET_PCI=y +-CONFIG_PCNET_COMMON=y + CONFIG_AC97=y + CONFIG_HDA=y + CONFIG_RTL8139_PCI=y + CONFIG_E1000_PCI=y +-CONFIG_VMXNET3_PCI=y + CONFIG_IDE_CORE=y + CONFIG_IDE_QDEV=y + CONFIG_IDE_PCI=y +diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak +index cc3587f..5f70181 100644 +--- a/default-configs/ppc-softmmu.mak ++++ b/default-configs/ppc-softmmu.mak +@@ -34,7 +34,6 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y +-CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak +index 884ea8a..0e8ff62 100644 +--- a/default-configs/ppc64-softmmu.mak ++++ b/default-configs/ppc64-softmmu.mak +@@ -34,7 +34,6 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y +-CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak +index be93e03..a8ab6e3 100644 +--- a/default-configs/ppcemb-softmmu.mak ++++ b/default-configs/ppcemb-softmmu.mak +@@ -29,7 +29,6 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y +-CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak +index 8fc93dd..ddba71d 100644 +--- a/default-configs/sparc-softmmu.mak ++++ b/default-configs/sparc-softmmu.mak +@@ -7,7 +7,6 @@ CONFIG_M48T59=y + CONFIG_PTIMER=y + CONFIG_FDC=y + CONFIG_EMPTY_SLOT=y +-CONFIG_PCNET_COMMON=y + CONFIG_LANCE=y + CONFIG_TCX=y + CONFIG_SLAVIO=y +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index bd3a533..69cdda0 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -20,7 +20,6 @@ CONFIG_APM=y + CONFIG_I8257=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y +-CONFIG_NE2000_ISA=y + CONFIG_PIIX_PCI=y + CONFIG_HPET=y + CONFIG_I8259=y diff --git a/SOURCES/disable-unsupported-emulated-scsi-devices.patch b/SOURCES/disable-unsupported-emulated-scsi-devices.patch new file mode 100644 index 0000000..4332177 --- /dev/null +++ b/SOURCES/disable-unsupported-emulated-scsi-devices.patch @@ -0,0 +1,40 @@ +From f991d8c7f0d19ccc948ec6540487649adf20d99b Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 22 May 2013 08:45:03 +0200 +Subject: Disable unsupported emulated SCSI devices + +Bugzilla: 903918 + +We do not support following device so it has to be disabled: +- lsi53c895a +- am53c974 +- dc390 +- esp +- megasas +- pvscsi + +Signed-off-by: Miroslav Rezanina + +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index 78f1579..8ef7e50 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -11,9 +11,6 @@ CONFIG_PCNET_COMMON=y + CONFIG_AC97=y + CONFIG_HDA=y + CONFIG_ES1370=y +-CONFIG_LSI_SCSI_PCI=y +-CONFIG_VMW_PVSCSI_SCSI_PCI=y +-CONFIG_MEGASAS_SCSI_PCI=y + CONFIG_RTL8139_PCI=y + CONFIG_E1000_PCI=y + CONFIG_VMXNET3_PCI=y +@@ -21,8 +18,6 @@ CONFIG_IDE_CORE=y + CONFIG_IDE_QDEV=y + CONFIG_IDE_PCI=y + CONFIG_AHCI=y +-CONFIG_ESP=y +-CONFIG_ESP_PCI=y + CONFIG_SERIAL=y + CONFIG_SERIAL_PCI=y + CONFIG_IPACK=y diff --git a/SOURCES/disable-unsupported-usb-devices.patch b/SOURCES/disable-unsupported-usb-devices.patch new file mode 100644 index 0000000..0670681 --- /dev/null +++ b/SOURCES/disable-unsupported-usb-devices.patch @@ -0,0 +1,40 @@ +From ca2d050f0de557b4955f019402428487176925b6 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Mon, 22 Apr 2013 14:38:38 +0200 +Subject: Disable unsupported usb devices + +Bugzilla: 903914 + +Patch deactivates device we do not support in RHEL7: +- usb-audio +- usb-braille +- usb-bt-dongle +- usb-net +- usb-serial +- usb-wacom-tablet +- pci-ohci + +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index d557eab..78f1579 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -2,7 +2,6 @@ CONFIG_PCI=y + CONFIG_VIRTIO_PCI=y + CONFIG_VIRTIO=y + CONFIG_USB_UHCI=y +-CONFIG_USB_OHCI=y + CONFIG_USB_EHCI=y + CONFIG_USB_XHCI=y + CONFIG_NE2000_PCI=y +diff --git a/default-configs/usb.mak b/default-configs/usb.mak +index 1bf9075..9a3bd09 100644 +--- a/default-configs/usb.mak ++++ b/default-configs/usb.mak +@@ -2,7 +2,3 @@ CONFIG_USB_TABLET_WACOM=y + CONFIG_USB_STORAGE_BOT=y + CONFIG_USB_STORAGE_UAS=y + CONFIG_USB_SMARTCARD=y +-CONFIG_USB_AUDIO=y +-CONFIG_USB_SERIAL=y +-CONFIG_USB_NETWORK=y +-CONFIG_USB_BLUETOOTH=y diff --git a/SOURCES/disable-various-unsupported-devices.patch b/SOURCES/disable-various-unsupported-devices.patch new file mode 100644 index 0000000..3b19720 --- /dev/null +++ b/SOURCES/disable-various-unsupported-devices.patch @@ -0,0 +1,127 @@ +From 7a81bbb17a540bf7b83142333a9610c1d642ba09 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Tue, 19 Mar 2013 09:03:29 -0400 +Subject: Disable various unsupported devices + +Bugzilla: 921971 + +Disable following emulated devices we do not support: +- isa-applesmc +- vmware-svga +- ipoctal232 +- tpci200 +- ipack + +Signed-off-by: Miroslav Rezanina + +diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak +index 18e5337..f2792ad 100644 +--- a/default-configs/alpha-softmmu.mak ++++ b/default-configs/alpha-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_CIRRUS=y + CONFIG_IDE_CORE=y + CONFIG_IDE_QDEV=y +-CONFIG_VMWARE_VGA=y + CONFIG_IDE_CMD646=y + CONFIG_I8259=y + CONFIG_MC146818RTC=y +diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak +index 03deca2..b208e10 100644 +--- a/default-configs/i386-softmmu.mak ++++ b/default-configs/i386-softmmu.mak +@@ -8,7 +8,6 @@ CONFIG_QXL=$(CONFIG_SPICE) + CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y +@@ -24,7 +23,6 @@ CONFIG_IDE_PIIX=y + CONFIG_NE2000_ISA=y + CONFIG_PIIX_PCI=y + CONFIG_HPET=y +-CONFIG_APPLESMC=y + CONFIG_I8259=y + CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) +diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak +index b443702..4fed1ca 100644 +--- a/default-configs/mips-softmmu.mak ++++ b/default-configs/mips-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y + CONFIG_I8254=y +diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak +index d638957..5e4e758 100644 +--- a/default-configs/mips64-softmmu.mak ++++ b/default-configs/mips64-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y + CONFIG_I8254=y +diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak +index c9be3f4..cc54619 100644 +--- a/default-configs/mips64el-softmmu.mak ++++ b/default-configs/mips64el-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y + CONFIG_I8254=y +diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak +index 4f4a449..1e59e68 100644 +--- a/default-configs/mipsel-softmmu.mak ++++ b/default-configs/mipsel-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y + CONFIG_I8254=y +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index 8ef7e50..87334a4 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -20,6 +20,5 @@ CONFIG_IDE_PCI=y + CONFIG_AHCI=y + CONFIG_SERIAL=y + CONFIG_SERIAL_PCI=y +-CONFIG_IPACK=y + CONFIG_WDT_IB6300ESB=y + CONFIG_PCI_TESTDEV=y +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index 599b630..bd3a533 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -8,7 +8,6 @@ CONFIG_QXL=$(CONFIG_SPICE) + CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y +-CONFIG_VMWARE_VGA=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y + CONFIG_PARALLEL=y +@@ -24,7 +23,6 @@ CONFIG_IDE_PIIX=y + CONFIG_NE2000_ISA=y + CONFIG_PIIX_PCI=y + CONFIG_HPET=y +-CONFIG_APPLESMC=y + CONFIG_I8259=y + CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) diff --git a/SOURCES/e1000-Keep-capabilities-list-bit-on-for-older-RHEL-machine-types.patch b/SOURCES/e1000-Keep-capabilities-list-bit-on-for-older-RHEL-machine-types.patch new file mode 100644 index 0000000..c36f95a --- /dev/null +++ b/SOURCES/e1000-Keep-capabilities-list-bit-on-for-older-RHEL-machine-types.patch @@ -0,0 +1,49 @@ +From 5278c98d70ef98926e47b226cf5e40decc7ac7ca Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:06:40 +0200 +Subject: e1000: Keep capabilities list bit on for older RHEL machine types + +Message-id: <1375201922-6794-16-git-send-email-armbru@redhat.com> +Patchwork-id: 52825 +O-Subject: [RHEL-7 PATCH v3 15/15] e1000: Keep capabilities list bit on for older RHEL machine types +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Upstream commit dd8e937 "e1000: Don't set the Capabilities List bit" +switched it off. The necessary compat_props to keep it on for old +machine types were forgotten. + +The RHEL-6 backport commit 2d76e3e added property +e1000.x-__com_redhat_rhel630_compat, set it for 6.3 and older via +compat_props, and made setting the capabilities list bit depend on it +being set. + +Instead of porting the RHEL-only property forward to RHEL-7, use +upstream's e1000.autonegotiation, which is on for 6.4 and newer, else +off. This is admittedly a hack. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index e6f46f0..661b461 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1324,6 +1324,16 @@ static int pci_e1000_init(PCIDevice *pci_dev) + + pci_conf = d->dev.config; + ++ if (!(d->compat_flags & E1000_FLAG_AUTONEG)) { ++ /* ++ * We have no capabilities, so capability list bit should normally be 0. ++ * Keep it on for compat machine types to avoid breaking migration. ++ * HACK: abuse E1000_FLAG_AUTONEG, which is off exactly for ++ * the machine types that need this. ++ */ ++ pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST); ++ } ++ + /* TODO: RST# value should be 0, PCI spec 6.2.4 */ + pci_conf[PCI_CACHE_LINE_SIZE] = 0x10; + diff --git a/SOURCES/ksm.service b/SOURCES/ksm.service new file mode 100644 index 0000000..ccc2767 --- /dev/null +++ b/SOURCES/ksm.service @@ -0,0 +1,13 @@ +[Unit] +Description=Kernel Samepage Merging +ConditionPathExists=/sys/kernel/mm/ksm + +[Service] +Type=oneshot +RemainAfterExit=yes +EnvironmentFile=-/etc/sysconfig/ksm +ExecStart=/lib/systemd/ksmctl start +ExecStop=/lib/systemd/ksmctl stop + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/ksm.sysconfig b/SOURCES/ksm.sysconfig new file mode 100644 index 0000000..d99656d --- /dev/null +++ b/SOURCES/ksm.sysconfig @@ -0,0 +1,4 @@ +# The maximum number of unswappable kernel pages +# which may be allocated by ksm (0 for unlimited) +# If unset, defaults to half of total memory +# KSM_MAX_KERNEL_PAGES= diff --git a/SOURCES/ksmctl.c b/SOURCES/ksmctl.c new file mode 100644 index 0000000..af39591 --- /dev/null +++ b/SOURCES/ksmctl.c @@ -0,0 +1,77 @@ +/* Start/stop KSM, for systemd. + * Copyright (C) 2009, 2011 Red Hat, Inc. + * Written by Paolo Bonzini . + * Based on the original sysvinit script by Dan Kenigsberg + * This file is distributed under the GNU General Public License, version 2 + * or later. */ + +#include +#include +#include +#include +#include +#include + +#define KSM_MAX_KERNEL_PAGES_FILE "/sys/kernel/mm/ksm/max_kernel_pages" +#define KSM_RUN_FILE "/sys/kernel/mm/ksm/run" + +char *program_name; + +int usage(void) +{ + fprintf(stderr, "Usage: %s {start|stop}\n", program_name); + return 1; +} + +int write_value(uint64_t value, char *filename) +{ + FILE *fp; + if (!(fp = fopen(filename, "w")) || + fprintf(fp, "%llu\n", (unsigned long long) value) == EOF || + fflush(fp) == EOF || + fclose(fp) == EOF) + return 1; + + return 0; +} + +uint64_t ksm_max_kernel_pages() +{ + char *var = getenv("KSM_MAX_KERNEL_PAGES"); + char *endptr; + uint64_t value; + if (var && *var) { + value = strtoll(var, &endptr, 0); + if (value < LLONG_MAX && !*endptr) + return value; + } + /* Unless KSM_MAX_KERNEL_PAGES is set, let KSM munch up to half of + * total memory. */ + return sysconf(_SC_PHYS_PAGES) / 2; +} + +int start(void) +{ + if (access(KSM_MAX_KERNEL_PAGES_FILE, R_OK) >= 0) + write_value(ksm_max_kernel_pages(), KSM_MAX_KERNEL_PAGES_FILE); + return write_value(1, KSM_RUN_FILE); +} + +int stop(void) +{ + return write_value(0, KSM_RUN_FILE); +} + +int main(int argc, char **argv) +{ + program_name = argv[0]; + if (argc < 2) { + return usage(); + } else if (!strcmp(argv[1], "start")) { + return start(); + } else if (!strcmp(argv[1], "stop")) { + return stop(); + } else { + return usage(); + } +} diff --git a/SOURCES/ksmtuned b/SOURCES/ksmtuned new file mode 100644 index 0000000..c59dec0 --- /dev/null +++ b/SOURCES/ksmtuned @@ -0,0 +1,137 @@ +#!/bin/bash +# +# Copyright 2009 Red Hat, Inc. and/or its affiliates. +# Released under the GPL +# +# Author: Dan Kenigsberg +# +# ksmtuned - a simple script that controls whether (and with what vigor) ksm +# should search for duplicated pages. +# +# starts ksm when memory commited to qemu processes exceeds a threshold, and +# make ksm work harder and harder untill memory load falls below that +# threshold. +# +# send SIGUSR1 to this process right after a new qemu process is started, or +# following its death, to retune ksm accordingly +# +# needs testing and ironing. contact danken@redhat.com if something breaks. + +if [ -f /etc/ksmtuned.conf ]; then + . /etc/ksmtuned.conf +fi + +debug() { + if [ -n "$DEBUG" ]; then + s="`/bin/date`: $*" + [ -n "$LOGFILE" ] && echo "$s" >> "$LOGFILE" || echo "$s" + fi +} + + +KSM_MONITOR_INTERVAL=${KSM_MONITOR_INTERVAL:-60} +KSM_NPAGES_BOOST=${KSM_NPAGES_BOOST:-300} +KSM_NPAGES_DECAY=${KSM_NPAGES_DECAY:--50} + +KSM_NPAGES_MIN=${KSM_NPAGES_MIN:-64} +KSM_NPAGES_MAX=${KSM_NPAGES_MAX:-1250} +# millisecond sleep between ksm scans for 16Gb server. Smaller servers sleep +# more, bigger sleep less. +KSM_SLEEP_MSEC=${KSM_SLEEP_MSEC:-10} + +KSM_THRES_COEF=${KSM_THRES_COEF:-20} +KSM_THRES_CONST=${KSM_THRES_CONST:-2048} + +total=`awk '/^MemTotal:/ {print $2}' /proc/meminfo` +debug total $total + +npages=0 +sleep=$[KSM_SLEEP_MSEC * 16 * 1024 * 1024 / total] +[ $sleep -le 10 ] && sleep=10 +debug sleep $sleep +thres=$[total * KSM_THRES_COEF / 100] +if [ $KSM_THRES_CONST -gt $thres ]; then + thres=$KSM_THRES_CONST +fi +debug thres $thres + +KSMCTL () { + case x$1 in + xstop) + echo 0 > /sys/kernel/mm/ksm/run + ;; + xstart) + echo $2 > /sys/kernel/mm/ksm/pages_to_scan + echo $3 > /sys/kernel/mm/ksm/sleep_millisecs + echo 1 > /sys/kernel/mm/ksm/run + ;; + esac +} + +committed_memory () { + # calculate how much memory is committed to running qemu processes + local progname + progname=${1:-qemu-kvm} + ps -C "$progname" -o rsz | awk '{ sum += $1 }; END { print sum }' +} + +free_memory () { + awk '/^(MemFree|Buffers|Cached):/ {free += $2}; END {print free}' \ + /proc/meminfo +} + +increase_npages() { + local delta + delta=${1:-0} + npages=$[npages + delta] + if [ $npages -lt $KSM_NPAGES_MIN ]; then + npages=$KSM_NPAGES_MIN + elif [ $npages -gt $KSM_NPAGES_MAX ]; then + npages=$KSM_NPAGES_MAX + fi + echo $npages +} + + +adjust () { + local free committed + free=`free_memory` + committed=`committed_memory` + debug committed $committed free $free + if [ $[committed + thres] -lt $total -a $free -gt $thres ]; then + KSMCTL stop + debug "$[committed + thres] < $total and free > $thres, stop ksm" + return 1 + fi + debug "$[committed + thres] > $total, start ksm" + if [ $free -lt $thres ]; then + npages=`increase_npages $KSM_NPAGES_BOOST` + debug "$free < $thres, boost" + else + npages=`increase_npages $KSM_NPAGES_DECAY` + debug "$free > $thres, decay" + fi + KSMCTL start $npages $sleep + debug "KSMCTL start $npages $sleep" + return 0 +} + +function nothing () { + : +} + +loop () { + trap nothing SIGUSR1 + while true + do + sleep $KSM_MONITOR_INTERVAL & + wait $! + adjust + done +} + +PIDFILE=${PIDFILE-/var/run/ksmtune.pid} +if touch "$PIDFILE"; then + loop & + echo $! > "$PIDFILE" +fi diff --git a/SOURCES/ksmtuned.conf b/SOURCES/ksmtuned.conf new file mode 100644 index 0000000..fc4518c --- /dev/null +++ b/SOURCES/ksmtuned.conf @@ -0,0 +1,21 @@ +# Configuration file for ksmtuned. + +# How long ksmtuned should sleep between tuning adjustments +# KSM_MONITOR_INTERVAL=60 + +# Millisecond sleep between ksm scans for 16Gb server. +# Smaller servers sleep more, bigger sleep less. +# KSM_SLEEP_MSEC=10 + +# KSM_NPAGES_BOOST=300 +# KSM_NPAGES_DECAY=-50 +# KSM_NPAGES_MIN=64 +# KSM_NPAGES_MAX=1250 + +# KSM_THRES_COEF=20 +# KSM_THRES_CONST=2048 + +# uncomment the following if you want ksmtuned debug info + +# LOGFILE=/var/log/ksmtuned +# DEBUG=1 diff --git a/SOURCES/ksmtuned.service b/SOURCES/ksmtuned.service new file mode 100644 index 0000000..39febcc --- /dev/null +++ b/SOURCES/ksmtuned.service @@ -0,0 +1,12 @@ +[Unit] +Description=Kernel Samepage Merging (KSM) Tuning Daemon +After=ksm.service +Requires=ksm.service + +[Service] +ExecStart=/usr/sbin/ksmtuned +ExecReload=/bin/kill -USR1 $MAINPID +Type=forking + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/kvm-Build-ceph-rbd-only-for-rhev.patch b/SOURCES/kvm-Build-ceph-rbd-only-for-rhev.patch new file mode 100644 index 0000000..65703c6 --- /dev/null +++ b/SOURCES/kvm-Build-ceph-rbd-only-for-rhev.patch @@ -0,0 +1,100 @@ +From 5d5af5b18e07ef4c97a45feeaad3fe493d38f427 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 6 Nov 2013 15:43:26 +0100 +Subject: [PATCH 60/81] Build ceph/rbd only for rhev + +RH-Author: Miroslav Rezanina +Message-id: <58854c39ceb485b1ea685c02398db4462493dd35.1383752552.git.mrezanin@redhat.com> +Patchwork-id: 55544 +O-Subject: [RHEL7 qemu-kvm PATCH] Build ceph/rbd only for rhev +Bugzilla: 987583 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi + +From: Miroslav Rezanina + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=987583 +Brewbuild: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6536646 (RHEL) +Brewbuild: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6536615 (RHEV) + +We support ceph/rbd only for rhev qemu-kvm so it has to be disabled for rhel +qemu-kvm. This patch forwardport RHEL-6 way of disabling rbd but use new +way of handling introduced by Jeff Cody. + +This patch is based on Jeff's "RHEL Storage Differentiation" series and should be +applied with it. Both brew build include all 4 differentiation patches. + +Signed-off-by: Miroslav Rezanina +--- + block/Makefile.objs | 2 +- + configure | 11 +++++++++++ + redhat/qemu-kvm.spec.template | 6 ++++++ + 3 files changed, 18 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/Makefile.objs | 2 +- + configure | 11 +++++++++++ + redhat/qemu-kvm.spec.template | 6 ++++++ + 3 files changed, 18 insertions(+), 1 deletions(-) + +diff --git a/block/Makefile.objs b/block/Makefile.objs +index f355271..41a284b 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -12,7 +12,7 @@ ifeq ($(CONFIG_POSIX),y) + block-obj-y += nbd.o sheepdog.o + block-obj-$(CONFIG_LIBISCSI) += iscsi.o + block-obj-$(CONFIG_CURL) += curl.o +-block-obj-y += rbd.o ++block-obj-$(CONFIG_CEPH_SUPPORT) += rbd.o + block-obj-$(CONFIG_GLUSTERFS) += gluster.o + block-obj-$(CONFIG_LIBSSH2) += ssh.o + endif +diff --git a/configure b/configure +index d658434..1af1079 100755 +--- a/configure ++++ b/configure +@@ -242,6 +242,7 @@ tpm="no" + libssh2="" + live_block_ops="yes" + live_block_migration="no" ++ceph_support="yes" + + # parse CC options first + for opt do +@@ -937,6 +938,10 @@ for opt do + ;; + --enable-live-block-migration) live_block_migration="yes" + ;; ++ --disable-ceph-support) ceph_support=="no" ++ ;; ++ --enable-ceph-support) ceph_support=="yes" ++ ;; + *) echo "ERROR: unknown option $opt"; show_help="yes" + ;; + esac +@@ -1209,6 +1214,8 @@ echo " --disable-live-block-ops disable live block operations support" + echo " --enable-live-block-ops enable live block operations support" + echo " --disable-live-block-migration disable live block migration" + echo " --enable-live-block-migration enable live block migration" ++echo " --disable-ceph-support disable support for rbd block driver support" ++echo " --enable-ceph-support enable support for rbd block driver support" + echo "" + echo "NOTE: The object files are built at the place where configure is launched" + exit 1 +@@ -3964,6 +3971,10 @@ if test "$live_block_migration" = "yes" ; then + echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak + fi + ++if test "ceph_support" = "yes"; then ++ echo "CONFIG_CEPH_SUPPORT=y" >> $config_host_mak ++fi ++ + # USB host support + if test "$libusb" = "yes"; then + echo "HOST_USB=libusb legacy" >> $config_host_mak +-- +1.7.1 + diff --git a/SOURCES/kvm-Convert-stderr-message-calling-error_get_pretty-to-e.patch b/SOURCES/kvm-Convert-stderr-message-calling-error_get_pretty-to-e.patch new file mode 100644 index 0000000..ba9f8b1 --- /dev/null +++ b/SOURCES/kvm-Convert-stderr-message-calling-error_get_pretty-to-e.patch @@ -0,0 +1,219 @@ +From a52fe59a941e8cfa7b94ecc743ffcfcf0e1bcda7 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 28 Aug 2013 15:50:45 +0200 +Subject: [PATCH 28/28] Convert stderr message calling error_get_pretty() to error_report() + +RH-Author: Laszlo Ersek +Message-id: <1377705045-1054-3-git-send-email-lersek@redhat.com> +Patchwork-id: 53887 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 2/2] Convert stderr message calling error_get_pretty() to error_report() +Bugzilla: 906937 +RH-Acked-by: Michal Novotny +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +Convert stderr messages calling error_get_pretty() +to error_report(). + +Timestamp is prepended by -msg timstamp option with it. + +Per Markus's comment below, A conversion from fprintf() to +error_report() is always an improvement, regardless of +error_get_pretty(). + +http://marc.info/?l=qemu-devel&m=137513283408601&w=2 + +But, it is not reasonable to convert them at one time +because fprintf() is used everwhere in qemu. + +So, it should be done step by step with avoiding regression. + +Signed-off-by: Seiji Aguchi +Reviewed-by: Laszlo Ersek +Signed-off-by: Luiz Capitulino +(cherry picked from commit 4a44d85e28bd282f53ccf0fa933dd71b8744a229) + +Conflicts: + + hw/char/serial.c + +RHEL-7 notes: + +- I dropped the "hw/char/serial.c" hunks because they depend on + upstream commit db895a1e ("isa: Use realizefn for ISADevice"): + + - serial_init_core(s); + + serial_realize_core(s, &err); + + Upstream commit db895a1e was first tagged in v1.6.0-rc0 and we don't + have it. + + Instead, I replaced the fprintf(stderr, ...) call in serial_init_core() + with a matching error_report() call, following Stefan's review of v2 + 2/2. +Signed-off-by: Laszlo Ersek +--- + arch_init.c | 4 ++-- + hw/char/serial.c | 3 ++- + hw/i386/pc.c | 6 +++--- + qemu-char.c | 2 +- + target-i386/cpu.c | 2 +- + target-ppc/translate_init.c | 3 ++- + vl.c | 9 +++++---- + 7 files changed, 16 insertions(+), 13 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + arch_init.c | 4 ++-- + hw/char/serial.c | 3 ++- + hw/i386/pc.c | 6 +++--- + qemu-char.c | 2 +- + target-i386/cpu.c | 2 +- + target-ppc/translate_init.c | 3 ++- + vl.c | 9 +++++---- + 7 files changed, 16 insertions(+), 13 deletions(-) + +diff --git a/arch_init.c b/arch_init.c +index 30edd5f..cd2bb5a 100644 +--- a/arch_init.c ++++ b/arch_init.c +@@ -1069,8 +1069,8 @@ void do_acpitable_option(const QemuOpts *opts) + + acpi_table_add(opts, &err); + if (err) { +- fprintf(stderr, "Wrong acpi table provided: %s\n", +- error_get_pretty(err)); ++ error_report("Wrong acpi table provided: %s", ++ error_get_pretty(err)); + error_free(err); + exit(1); + } +diff --git a/hw/char/serial.c b/hw/char/serial.c +index 66b6348..0c472e2 100644 +--- a/hw/char/serial.c ++++ b/hw/char/serial.c +@@ -27,6 +27,7 @@ + #include "sysemu/char.h" + #include "qemu/timer.h" + #include "exec/address-spaces.h" ++#include "qemu/error-report.h" + + //#define DEBUG_SERIAL + +@@ -673,7 +674,7 @@ static void serial_reset(void *opaque) + void serial_init_core(SerialState *s) + { + if (!s->chr) { +- fprintf(stderr, "Can't create serial device, empty char device\n"); ++ error_report("Can't create serial device, empty char device"); + exit(1); + } + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index a7ecfb0..71b7a26 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -968,7 +968,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) + cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i), + icc_bridge, &error); + if (error) { +- fprintf(stderr, "%s\n", error_get_pretty(error)); ++ error_report("%s", error_get_pretty(error)); + error_free(error); + exit(1); + } +@@ -1007,8 +1007,8 @@ void pc_acpi_init(const char *default_dsdt) + + acpi_table_add(opts, &err); + if (err) { +- fprintf(stderr, "WARNING: failed to load %s: %s\n", filename, +- error_get_pretty(err)); ++ error_report("WARNING: failed to load %s: %s", filename, ++ error_get_pretty(err)); + error_free(err); + } + g_free(arg); +diff --git a/qemu-char.c b/qemu-char.c +index ccc9912..566267a 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3334,7 +3334,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in + + chr = qemu_chr_new_from_opts(opts, init, &err); + if (error_is_set(&err)) { +- fprintf(stderr, "%s\n", error_get_pretty(err)); ++ error_report("%s", error_get_pretty(err)); + error_free(err); + } + if (chr && qemu_opt_get_bool(opts, "mux", 0)) { +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 0ad8259..355375b 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -1847,7 +1847,7 @@ X86CPU *cpu_x86_init(const char *cpu_model) + + out: + if (error) { +- fprintf(stderr, "%s\n", error_get_pretty(error)); ++ error_report("%s", error_get_pretty(error)); + error_free(error); + if (cpu != NULL) { + object_unref(OBJECT(cpu)); +diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c +index 2e2bffa..5a12c0e 100644 +--- a/target-ppc/translate_init.c ++++ b/target-ppc/translate_init.c +@@ -27,6 +27,7 @@ + #include "cpu-models.h" + #include "mmu-hash32.h" + #include "mmu-hash64.h" ++#include "qemu/error-report.h" + + //#define PPC_DUMP_CPU + //#define PPC_DEBUG_SPR +@@ -8027,7 +8028,7 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model) + + object_property_set_bool(OBJECT(cpu), true, "realized", &err); + if (err != NULL) { +- fprintf(stderr, "%s\n", error_get_pretty(err)); ++ error_report("%s", error_get_pretty(err)); + error_free(err); + object_unref(OBJECT(cpu)); + return NULL; +diff --git a/vl.c b/vl.c +index 0ce554d..51c04e7 100644 +--- a/vl.c ++++ b/vl.c +@@ -2363,7 +2363,7 @@ static int chardev_init_func(QemuOpts *opts, void *opaque) + + qemu_chr_new_from_opts(opts, NULL, &local_err); + if (error_is_set(&local_err)) { +- fprintf(stderr, "%s\n", error_get_pretty(local_err)); ++ error_report("%s", error_get_pretty(local_err)); + error_free(local_err); + return -1; + } +@@ -4393,8 +4393,8 @@ int main(int argc, char **argv, char **envp) + vnc_display_init(ds); + vnc_display_open(ds, vnc_display, &local_err); + if (local_err != NULL) { +- fprintf(stderr, "Failed to start VNC server on `%s': %s\n", +- vnc_display, error_get_pretty(local_err)); ++ error_report("Failed to start VNC server on `%s': %s", ++ vnc_display, error_get_pretty(local_err)); + error_free(local_err); + exit(1); + } +@@ -4437,7 +4437,8 @@ int main(int argc, char **argv, char **envp) + Error *local_err = NULL; + qemu_start_incoming_migration(incoming, &local_err); + if (local_err) { +- fprintf(stderr, "-incoming %s: %s\n", incoming, error_get_pretty(local_err)); ++ error_report("-incoming %s: %s", incoming, ++ error_get_pretty(local_err)); + error_free(local_err); + exit(1); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-Disable-isa-parallel.patch b/SOURCES/kvm-Disable-isa-parallel.patch new file mode 100644 index 0000000..2946508 --- /dev/null +++ b/SOURCES/kvm-Disable-isa-parallel.patch @@ -0,0 +1,158 @@ +From 50a34ddf34ea04ffddc36b16401ddcb0c5679e80 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Fri, 30 Aug 2013 08:51:26 +0200 +Subject: [PATCH 07/29] Disable isa-parallel + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 53938 +O-Subject: [RHEL7 qemu-kvm PATCHv2 6/6] Disable isa-parallel +Bugzilla: 1002286 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +We are not going to support isa-parallel device so disabling it. + +Signed-off-by: Miroslav Rezanina + +v2: + - new patch +--- + default-configs/i386-softmmu.mak | 1 - + default-configs/mips-softmmu.mak | 1 - + default-configs/mips64-softmmu.mak | 1 - + default-configs/mips64el-softmmu.mak | 1 - + default-configs/mipsel-softmmu.mak | 1 - + default-configs/ppc-softmmu.mak | 1 - + default-configs/ppc64-softmmu.mak | 1 - + default-configs/sparc64-softmmu.mak | 1 - + default-configs/x86_64-softmmu.mak | 1 - + 9 files changed, 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/i386-softmmu.mak | 1 - + default-configs/mips-softmmu.mak | 1 - + default-configs/mips64-softmmu.mak | 1 - + default-configs/mips64el-softmmu.mak | 1 - + default-configs/mipsel-softmmu.mak | 1 - + default-configs/ppc-softmmu.mak | 1 - + default-configs/ppc64-softmmu.mak | 1 - + default-configs/sparc64-softmmu.mak | 1 - + default-configs/x86_64-softmmu.mak | 1 - + 9 files changed, 0 insertions(+), 9 deletions(-) + +diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak +index cf6ee9f..54df7bd 100644 +--- a/default-configs/i386-softmmu.mak ++++ b/default-configs/i386-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak +index 3c5fb43..b4eef8c 100644 +--- a/default-configs/mips-softmmu.mak ++++ b/default-configs/mips-softmmu.mak +@@ -11,7 +11,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak +index c05d44a..c7a9232 100644 +--- a/default-configs/mips64-softmmu.mak ++++ b/default-configs/mips64-softmmu.mak +@@ -11,7 +11,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak +index 40aaea5..79bdfdb 100644 +--- a/default-configs/mips64el-softmmu.mak ++++ b/default-configs/mips64el-softmmu.mak +@@ -11,7 +11,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak +index ca44d0e..beb6819 100644 +--- a/default-configs/mipsel-softmmu.mak ++++ b/default-configs/mipsel-softmmu.mak +@@ -11,7 +11,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak +index 5f70181..7f6ea0f 100644 +--- a/default-configs/ppc-softmmu.mak ++++ b/default-configs/ppc-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_M48T59=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCKBD=y + CONFIG_FDC=y +diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak +index 0e8ff62..29a8be6 100644 +--- a/default-configs/ppc64-softmmu.mak ++++ b/default-configs/ppc64-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_M48T59=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCKBD=y + CONFIG_FDC=y +diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak +index 9b08ee8..2998f34 100644 +--- a/default-configs/sparc64-softmmu.mak ++++ b/default-configs/sparc64-softmmu.mak +@@ -8,7 +8,6 @@ CONFIG_PTIMER=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_PCKBD=y + CONFIG_FDC=y + CONFIG_IDE_ISA=y +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index 4234f00..05cc2a3 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -10,7 +10,6 @@ CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y +-CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +-- +1.7.1 + diff --git a/SOURCES/kvm-Disable-usb-uas.patch b/SOURCES/kvm-Disable-usb-uas.patch new file mode 100644 index 0000000..4982d66 --- /dev/null +++ b/SOURCES/kvm-Disable-usb-uas.patch @@ -0,0 +1,44 @@ +From 99ea614bff3d383fbd6910ae0d66912fc15eba57 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Fri, 30 Aug 2013 08:51:23 +0200 +Subject: [PATCH 04/29] Disable usb-uas + +RH-Author: Miroslav Rezanina +Message-id: <95623a002492b1f8117e0f99e2b1163f2a2a4071.1377851454.git.mrezanin@redhat.com> +Patchwork-id: 53934 +O-Subject: [RHEL7 qemu-kvm PATCHv2 3/6] Disable usb-uas +Bugzilla: 903914 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +BZ: 903914 + +As usb3 streams are still broken, we do not need usb-uas device. + +v2: + - new patch +Signed-off-by: Miroslav Rezanina +--- + default-configs/usb.mak | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/usb.mak | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/default-configs/usb.mak b/default-configs/usb.mak +index 39a3552..55c37f0 100644 +--- a/default-configs/usb.mak ++++ b/default-configs/usb.mak +@@ -1,3 +1,2 @@ + CONFIG_USB_STORAGE_BOT=y +-CONFIG_USB_STORAGE_UAS=y + CONFIG_USB_SMARTCARD=y +-- +1.7.1 + diff --git a/SOURCES/kvm-Fix-machine-options-accel-kernel_irqchip-kvm_shadow_.patch b/SOURCES/kvm-Fix-machine-options-accel-kernel_irqchip-kvm_shadow_.patch new file mode 100644 index 0000000..f168ffa --- /dev/null +++ b/SOURCES/kvm-Fix-machine-options-accel-kernel_irqchip-kvm_shadow_.patch @@ -0,0 +1,178 @@ +From 63d9ae740b30071f01c5fd1196f077b635491530 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:03 +0200 +Subject: [PATCH 10/28] Fix -machine options accel, kernel_irqchip, kvm_shadow_mem + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-5-git-send-email-armbru@redhat.com> +Patchwork-id: 52993 +O-Subject: [PATCH 7.0 qemu-kvm 4/6] Fix -machine options accel, kernel_irqchip, kvm_shadow_mem +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +Multiple -machine options with the same ID are merged. All but the +one without an ID are to be silently ignored. + +In most places, we query these options with a null ID. This is +correct. + +In some places, we instead query whatever options come first in the +list. This is wrong. When the -machine processed first happens to +have an ID, options are taken from that ID, and the ones specified +without ID are silently ignored. + +Example: + + $ upstream-qemu -nodefaults -S -display none -monitor stdio -machine id=foo -machine accel=kvm,usb=on + $ upstream-qemu -nodefaults -S -display none -monitor stdio -machine id=foo,accel=kvm,usb=on -machine accel=xen + $ upstream-qemu -nodefaults -S -display none -monitor stdio -machine accel=xen -machine id=foo,accel=kvm,usb=on + + $ qemu-system-x86_64 -nodefaults -S -display none -monitor stdio -machine accel=kvm,usb=on + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) info kvm + kvm support: enabled + (qemu) info usb + (qemu) q + $ qemu-system-x86_64 -nodefaults -S -display none -monitor stdio -machine id=foo -machine accel=kvm,usb=on + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) info kvm + kvm support: disabled + (qemu) info usb + (qemu) q + $ qemu-system-x86_64 -nodefaults -S -display none -monitor stdio -machine id=foo,accel=kvm,usb=on -machine accel=xen + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) info kvm + kvm support: enabled + (qemu) info usb + USB support not enabled + (qemu) q + $ qemu-system-x86_64 -nodefaults -S -display none -monitor stdio -machine accel=xen -machine id=foo,accel=kvm,usb=on + xc: error: Could not obtain handle on privileged command interface (2 = No such file or directory): Internal error + xen be core: can't open xen interface + failed to initialize Xen: Operation not permitted + +Option usb is queried correctly, and the one without an ID wins, +regardless of option order. + +Option accel is queried incorrectly, and which one wins depends on +option order and ID. + +Affected options are accel (and its sugared forms -enable-kvm and +-no-kvm), kernel_irqchip, kvm_shadow_mem. + +Additionally, option kernel_irqchip is normally on by default, except +it's off when no -machine options are given. Bug can't bite, because +kernel_irqchip is used only when KVM is enabled, KVM is off by +default, and enabling always creates -machine options. Downstreams +that enable KVM by default do get bitten, though. + +Use qemu_get_machine_opts() to fix these bugs. + +Signed-off-by: Markus Armbruster +Message-id: 1372943363-24081-5-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 36ad0e948e15d8d86c8dec1c17a8588d87b0107d) + +Conflicts: + hw/ppc/e500.c + +Conflicts, because we don't have commit d85937e "kvm/openpic: +in-kernel mpic support". Resolution is trivial: drop the hunk. + +There's a pasto in upstream's commit message. The first paragraph +after "Example:" shouldn't be there. +--- + kvm-all.c | 5 +---- + target-i386/kvm.c | 17 +++++++---------- + vl.c | 8 ++------ + 3 files changed, 10 insertions(+), 20 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + kvm-all.c | 5 +---- + target-i386/kvm.c | 17 +++++++---------- + vl.c | 8 ++------ + 3 files changed, 10 insertions(+), 20 deletions(-) + +diff --git a/kvm-all.c b/kvm-all.c +index 8222729..6c9d51e 100644 +--- a/kvm-all.c ++++ b/kvm-all.c +@@ -1256,12 +1256,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) + + static int kvm_irqchip_create(KVMState *s) + { +- QemuOptsList *list = qemu_find_opts("machine"); + int ret; + +- if (QTAILQ_EMPTY(&list->head) || +- !qemu_opt_get_bool(QTAILQ_FIRST(&list->head), +- "kernel_irqchip", true) || ++ if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) || + !kvm_check_extension(s, KVM_CAP_IRQCHIP)) { + return 0; + } +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index 9ffb6ca..8da6a0d 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -741,7 +741,6 @@ static int kvm_get_supported_msrs(KVMState *s) + + int kvm_arch_init(KVMState *s) + { +- QemuOptsList *list = qemu_find_opts("machine"); + uint64_t identity_base = 0xfffbc000; + uint64_t shadow_mem; + int ret; +@@ -790,15 +789,13 @@ int kvm_arch_init(KVMState *s) + } + qemu_register_reset(kvm_unpoison_all, NULL); + +- if (!QTAILQ_EMPTY(&list->head)) { +- shadow_mem = qemu_opt_get_size(QTAILQ_FIRST(&list->head), +- "kvm_shadow_mem", -1); +- if (shadow_mem != -1) { +- shadow_mem /= 4096; +- ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem); +- if (ret < 0) { +- return ret; +- } ++ shadow_mem = qemu_opt_get_size(qemu_get_machine_opts(), ++ "kvm_shadow_mem", -1); ++ if (shadow_mem != -1) { ++ shadow_mem /= 4096; ++ ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem); ++ if (ret < 0) { ++ return ret; + } + } + return 0; +diff --git a/vl.c b/vl.c +index fe58eff..0ed9257 100644 +--- a/vl.c ++++ b/vl.c +@@ -2661,17 +2661,13 @@ static struct { + + static int configure_accelerator(void) + { +- const char *p = NULL; ++ const char *p; + char buf[10]; + int i, ret; + bool accel_initialised = false; + bool init_failed = false; + +- QemuOptsList *list = qemu_find_opts("machine"); +- if (!QTAILQ_EMPTY(&list->head)) { +- p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel"); +- } +- ++ p = qemu_opt_get(qemu_get_machine_opts(), "accel"); + if (p == NULL) { + /* Use the default "accelerator", tcg */ + p = "kvm:tcg"; +-- +1.7.1 + diff --git a/SOURCES/kvm-Fix-migration-from-rhel6.5-to-rhel7-with-ipxe.patch b/SOURCES/kvm-Fix-migration-from-rhel6.5-to-rhel7-with-ipxe.patch new file mode 100644 index 0000000..8f97f8b --- /dev/null +++ b/SOURCES/kvm-Fix-migration-from-rhel6.5-to-rhel7-with-ipxe.patch @@ -0,0 +1,58 @@ +From 5ed11d0f0f9cbd5e8616bd8f6028b8cae45c9103 Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Tue, 5 Nov 2013 13:13:44 +0100 +Subject: [PATCH 17/29] Fix migration from rhel6.5 to rhel7 with ipxe + +RH-Author: Orit Wasserman +Message-id: <1383657224-18599-4-git-send-email-owasserm@redhat.com> +Patchwork-id: 55377 +O-Subject: [RHEL-7.0 qemu-kvm 3/3] Fix migration from rhel6.5 to rhel7 with ipxe +Bugzilla: 997702 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Alex Williamson +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Juan Quintela + +Use rhel6 ipxe roms for rhel6 machine types (to have compatible roms sizes +when migrating) + +Signed-off-by: Orit Wasserman +--- + hw/i386/pc_piix.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 16 ++++++++++++++++ + 1 files changed, 16 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 3f5b913..3a8418e 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -867,6 +867,22 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "usb-ccid",\ + .property = "serial",\ + .value = "1",\ ++ },{\ ++ .driver = "ne2k_pci",\ ++ .property = "romfile",\ ++ .value = "rhel6-ne2k_pci.rom",\ ++ },{\ ++ .driver = "pcnet",\ ++ .property = "romfile",\ ++ .value = "rhel6-pcnet.rom",\ ++ },{\ ++ .driver = "rtl8139",\ ++ .property = "romfile",\ ++ .value = "rhel6-rtl8139.rom",\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "romfile",\ ++ .value = "rhel6-virtio.rom",\ + } + + static void pc_init_rhel650(QEMUMachineInitArgs *args) +-- +1.7.1 + diff --git a/SOURCES/kvm-Fix-potential-resource-leak-missing-fclose.patch b/SOURCES/kvm-Fix-potential-resource-leak-missing-fclose.patch new file mode 100644 index 0000000..14db562 --- /dev/null +++ b/SOURCES/kvm-Fix-potential-resource-leak-missing-fclose.patch @@ -0,0 +1,47 @@ +From 803bf1ab08aadf547f8e45f0a727c17bb2b96ca5 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 1 Nov 2013 19:50:32 +0100 +Subject: [PATCH 02/25] kvm: Fix potential resource leak (missing fclose) + +RH-Author: Alex Williamson +Message-id: <20131101195032.25461.97296.stgit@bling.home> +Patchwork-id: 55234 +O-Subject: [RHEL7 qemu-kvm PATCH 2/3] kvm: Fix potential resource leak (missing fclose) +Bugzilla: 1025877 +RH-Acked-by: Bandan Das +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Orit Wasserman + +From: Stefan Weil + +Bugzilla: 1025877 +Upstream commit: 90527d2a8bb08ca5b4774eacfdd6b8fe9671c077 + +This leak was detected by cppcheck. + +Signed-off-by: Stefan Weil +Signed-off-by: Michael Tokarev +--- + hw/i386/kvm/pci-assign.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvm/pci-assign.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c +index 221a8f7..a5885b4 100644 +--- a/hw/i386/kvm/pci-assign.c ++++ b/hw/i386/kvm/pci-assign.c +@@ -548,6 +548,7 @@ static int get_real_id(const char *devpath, const char *idname, uint16_t *val) + if (fscanf(f, "%li\n", &id) == 1) { + *val = id; + } else { ++ fclose(f); + return -1; + } + fclose(f); +-- +1.7.1 + diff --git a/SOURCES/kvm-Fix-real-mode-guest-migration.patch b/SOURCES/kvm-Fix-real-mode-guest-migration.patch new file mode 100644 index 0000000..6b0d21c --- /dev/null +++ b/SOURCES/kvm-Fix-real-mode-guest-migration.patch @@ -0,0 +1,67 @@ +From c576ee9550d38273808c2055803f3a254655753e Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:10 +0200 +Subject: [PATCH 15/25] Fix real mode guest migration + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-6-git-send-email-owasserm@redhat.com> +Patchwork-id: 54801 +O-Subject: [RHEL7.0 qemu-kvm v2 05/10] Fix real mode guest migration +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +Older KVM versions save CS dpl value to an invalid value for real mode guests +(0x3). This patch detect this situation when loading CPU state and set all the +segments dpl to zero. +This will allow migration from older KVM on host without unrestricted guest +to hosts with restricted guest support. +For example migration from a Penryn host (with kernel 2.6.32) to +a Westmere host (for real mode guest) will fail with "kvm: unhandled exit 80000021". + +Signed-off-by: Orit Wasserman +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +(cherry picked from commit 444ba6797ef6ef331fe9fd34309b1ec59caaede3) +--- + target-i386/machine.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/machine.c | 18 ++++++++++++++++++ + 1 files changed, 18 insertions(+), 0 deletions(-) + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index ecf1617..079a132 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -260,6 +260,24 @@ static int cpu_post_load(void *opaque, int version_id) + CPUX86State *env = &cpu->env; + int i; + ++ /* ++ * Real mode guest segments register DPL should be zero. ++ * Older KVM version were setting it wrongly. ++ * Fixing it will allow live migration from such host that don't have ++ * restricted guest support to a host with unrestricted guest support ++ * (otherwise the migration will fail with invalid guest state ++ * error). ++ */ ++ if (!(env->cr[0] & CR0_PE_MASK) && ++ (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) { ++ env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK); ++ env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK); ++ env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK); ++ env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK); ++ env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK); ++ env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK); ++ } ++ + /* XXX: restore FPU round state */ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; +-- +1.7.1 + diff --git a/SOURCES/kvm-Fix-real-mode-guest-segments-dpl-value-in-savevm.patch b/SOURCES/kvm-Fix-real-mode-guest-segments-dpl-value-in-savevm.patch new file mode 100644 index 0000000..9527d4c --- /dev/null +++ b/SOURCES/kvm-Fix-real-mode-guest-segments-dpl-value-in-savevm.patch @@ -0,0 +1,65 @@ +From 38c385caa32752ef176ffd1448e45e0dc94d5043 Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:11 +0200 +Subject: [PATCH 16/25] Fix real mode guest segments dpl value in savevm + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-7-git-send-email-owasserm@redhat.com> +Patchwork-id: 54802 +O-Subject: [RHEL7.0 qemu-kvm v2 06/10] Fix real mode guest segments dpl value in savevm +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +Older KVM version put invalid value in the segments registers dpl field for +real mode guests (0x3). +This breaks migration from those hosts to hosts with unrestricted guest support. +We detect it by checking CS dpl value for real mode guest and fix the dpl values +of all the segment registers. + +Signed-off-by: Orit Wasserman +Reviewed-by: Juan Quintela +Signed-off-by: Juan Quintela +(cherry picked from commit 3e47c249b93d5cc1e0f9404dbe243682598ba8fb) +--- + target-i386/machine.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/machine.c | 18 ++++++++++++++++++ + 1 files changed, 18 insertions(+), 0 deletions(-) + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 079a132..8faea62 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -252,6 +252,24 @@ static void cpu_pre_save(void *opaque) + } + + env->fpregs_format_vmstate = 0; ++ ++ /* ++ * Real mode guest segments register DPL should be zero. ++ * Older KVM version were setting it wrongly. ++ * Fixing it will allow live migration to host with unrestricted guest ++ * support (otherwise the migration will fail with invalid guest state ++ * error). ++ */ ++ if (!(env->cr[0] & CR0_PE_MASK) && ++ (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) { ++ env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK); ++ env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK); ++ env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK); ++ env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK); ++ env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK); ++ env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK); ++ } ++ + } + + static int cpu_post_load(void *opaque, int version_id) +-- +1.7.1 + diff --git a/SOURCES/kvm-Implement-qdict_flatten.patch b/SOURCES/kvm-Implement-qdict_flatten.patch new file mode 100644 index 0000000..9dde647 --- /dev/null +++ b/SOURCES/kvm-Implement-qdict_flatten.patch @@ -0,0 +1,107 @@ +From 4c0ae9bbc7424ca9fc220f56487e9927e8841f87 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:00 +0100 +Subject: [PATCH 47/87] Implement qdict_flatten() + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-7-git-send-email-kwolf@redhat.com> +Patchwork-id: 55385 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 06/24] Implement qdict_flatten() +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +qdict_flatten(): For each nested QDict with key x, all fields with key y +are moved to this QDict and their key is renamed to "x.y". This operation +is applied recursively for nested QDicts. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit f660dc6a2e97756596b2e79ce6127a3034f2308b) + +Signed-off-by: Kevin Wolf +--- + include/qapi/qmp/qdict.h | 1 + + qobject/qdict.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + include/qapi/qmp/qdict.h | 1 + + qobject/qdict.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+), 0 deletions(-) + +diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h +index 685b2e3..d6855d1 100644 +--- a/include/qapi/qmp/qdict.h ++++ b/include/qapi/qmp/qdict.h +@@ -65,5 +65,6 @@ int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value); + const char *qdict_get_try_str(const QDict *qdict, const char *key); + + QDict *qdict_clone_shallow(const QDict *src); ++void qdict_flatten(QDict *qdict); + + #endif /* QDICT_H */ +diff --git a/qobject/qdict.c b/qobject/qdict.c +index ed381f9..472f106 100644 +--- a/qobject/qdict.c ++++ b/qobject/qdict.c +@@ -476,3 +476,54 @@ static void qdict_destroy_obj(QObject *obj) + + g_free(qdict); + } ++ ++static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) ++{ ++ QObject *value; ++ const QDictEntry *entry, *next; ++ const char *new_key; ++ bool delete; ++ ++ entry = qdict_first(qdict); ++ ++ while (entry != NULL) { ++ ++ next = qdict_next(qdict, entry); ++ value = qdict_entry_value(entry); ++ new_key = NULL; ++ delete = false; ++ ++ if (prefix) { ++ qobject_incref(value); ++ new_key = g_strdup_printf("%s.%s", prefix, entry->key); ++ qdict_put_obj(target, new_key, value); ++ delete = true; ++ } ++ ++ if (qobject_type(value) == QTYPE_QDICT) { ++ qdict_do_flatten(qobject_to_qdict(value), target, ++ new_key ? new_key : entry->key); ++ delete = true; ++ } ++ ++ if (delete) { ++ qdict_del(qdict, entry->key); ++ ++ /* Restart loop after modifying the iterated QDict */ ++ entry = qdict_first(qdict); ++ continue; ++ } ++ ++ entry = next; ++ } ++} ++ ++/** ++ * qdict_flatten(): For each nested QDict with key x, all fields with key y ++ * are moved to this QDict and their key is renamed to "x.y". This operation ++ * is applied recursively for nested QDicts. ++ */ ++void qdict_flatten(QDict *qdict) ++{ ++ qdict_do_flatten(qdict, qdict, NULL); ++} +-- +1.7.1 + diff --git a/SOURCES/kvm-Makefile-create-.-var-run-when-installing-the-POSIX-.patch b/SOURCES/kvm-Makefile-create-.-var-run-when-installing-the-POSIX-.patch new file mode 100644 index 0000000..b9c0ee4 --- /dev/null +++ b/SOURCES/kvm-Makefile-create-.-var-run-when-installing-the-POSIX-.patch @@ -0,0 +1,62 @@ +From b14a772332fe273f7c3430af03bcbb8ab5bcc3ae Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:27 +0200 +Subject: [PATCH 06/28] Makefile: create ".../var/run" when installing the POSIX guest agent + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-7-git-send-email-lersek@redhat.com> +Patchwork-id: 52864 +O-Subject: [RHEL-7 qemu-kvm PATCH 6/6] Makefile: create ".../var/run" when installing the POSIX guest agent +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +Otherwise the default local state directory of POSIX qga won't exist after +installation with a non-standard ${prefix} or DESTDIR. + +For now qga is the only user of ".../var" (= $qemu_localstatedir) too, so +don't create that directory either unless we're installing the agent. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael Roth +(cherry picked from commit f2e3978b5a72870b061d29948075dccc0a72db8e) +--- + Makefile | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + Makefile | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +diff --git a/Makefile b/Makefile +index dbd96d1..dcd31c6 100644 +--- a/Makefile ++++ b/Makefile +@@ -321,13 +321,21 @@ endif + install-datadir: + $(INSTALL_DIR) "$(DESTDIR)$(qemu_datadir)" + ++install-localstatedir: ++ifdef CONFIG_POSIX ++ifneq (,$(findstring qemu-ga,$(TOOLS))) ++ $(INSTALL_DIR) "$(DESTDIR)$(qemu_localstatedir)"/run ++endif ++endif ++ + install-confdir: + $(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)" + + install-sysconfig: install-datadir install-confdir + $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(qemu_confdir)" + +-install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir ++install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig \ ++install-datadir install-localstatedir + $(INSTALL_DIR) "$(DESTDIR)$(bindir)" + ifneq ($(TOOLS),) + $(INSTALL_PROG) $(STRIP_OPT) $(TOOLS) "$(DESTDIR)$(bindir)" +-- +1.7.1 + diff --git a/SOURCES/kvm-Mostly-revert-qemu-help-Sort-devices-by-logical-func.patch b/SOURCES/kvm-Mostly-revert-qemu-help-Sort-devices-by-logical-func.patch new file mode 100644 index 0000000..705c59b --- /dev/null +++ b/SOURCES/kvm-Mostly-revert-qemu-help-Sort-devices-by-logical-func.patch @@ -0,0 +1,177 @@ +From c028066b7a4a68d52a33f6856bb8fe907def2b6b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:10 +0100 +Subject: [PATCH 34/81] Mostly revert "qemu-help: Sort devices by logical functionality" + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-6-git-send-email-kwolf@redhat.com> +Patchwork-id: 55531 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 05/17] Mostly revert "qemu-help: Sort devices by logical functionality" +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +This reverts most of commit 3d1237fb2ab4edb926c717767bb5e31d6053a7c5. + +The commit claims to sort the output of "-device help" "by +functionality rather than alphabetical". Issues: + +* The output was unsorted before, not alphabetically sorted. + Misleading, but harmless enough. + +* The commit doesn't just sort the output of "-device help" as it + claims, it adds categories to each line of "-device help", and it + prints devices once per category. In particular, devices without a + category aren't shown anymore. Maybe such devices should not exist, + but they do. Regression. + +* Categories are also added to the output of "info qdm". Silent + change, not nice. Output remains unsorted, unlike "-device help". + +I'm going to reimplement the feature we actually want, without the +warts. Reverting the flawed commit first should make it easier to +review. However, I can't revert it completely, since DeviceClass +member categories has been put to use. So leave that part in. + +Signed-off-by: Markus Armbruster +Reviewed-by: Marcel Apfelbaum +Message-id: 1381410021-1538-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 1fc224b4b6d195fb7802d5ba1a0846a4e7a1e2af) +Signed-off-by: Kevin Wolf +--- + include/hw/qdev-core.h | 16 ---------------- + qdev-monitor.c | 48 +++++++++--------------------------------------- + 2 files changed, 9 insertions(+), 55 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/hw/qdev-core.h | 16 ---------------- + qdev-monitor.c | 48 +++++++++--------------------------------------- + 2 files changed, 9 insertions(+), 55 deletions(-) + +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 18596e9..a8618db 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -30,22 +30,6 @@ typedef enum DeviceCategory { + DEVICE_CATEGORY_MAX + } DeviceCategory; + +-static inline const char *qdev_category_get_name(DeviceCategory category) +-{ +- static const char *category_names[DEVICE_CATEGORY_MAX] = { +- [DEVICE_CATEGORY_BRIDGE] = "Controller/Bridge/Hub", +- [DEVICE_CATEGORY_USB] = "USB", +- [DEVICE_CATEGORY_STORAGE] = "Storage", +- [DEVICE_CATEGORY_NETWORK] = "Network", +- [DEVICE_CATEGORY_INPUT] = "Input", +- [DEVICE_CATEGORY_DISPLAY] = "Display", +- [DEVICE_CATEGORY_SOUND] = "Sound", +- [DEVICE_CATEGORY_MISC] = "Misc", +- }; +- +- return category_names[category]; +-}; +- + typedef int (*qdev_initfn)(DeviceState *dev); + typedef int (*qdev_event)(DeviceState *dev); + typedef void (*qdev_resetfn)(DeviceState *dev); +diff --git a/qdev-monitor.c b/qdev-monitor.c +index 230a8df..e54dbc2 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -75,27 +75,24 @@ static bool qdev_class_has_alias(DeviceClass *dc) + return (qdev_class_get_alias(dc) != NULL); + } + +-static void qdev_print_class_devinfo(DeviceClass *dc) ++static void qdev_print_devinfo(ObjectClass *klass, void *opaque) + { +- DeviceCategory category; ++ DeviceClass *dc; ++ bool *show_no_user = opaque; ++ ++ dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); + +- if (!dc) { ++ if (!dc || (show_no_user && !*show_no_user && dc->no_user)) { + return; + } + +- error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc))); ++ error_printf("name \"%s\"", object_class_get_name(klass)); + if (dc->bus_type) { + error_printf(", bus %s", dc->bus_type); + } + if (qdev_class_has_alias(dc)) { + error_printf(", alias \"%s\"", qdev_class_get_alias(dc)); + } +- error_printf(", categories"); +- for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) { +- if (test_bit(category, dc->categories)) { +- error_printf(" \"%s\"", qdev_category_get_name(category)); +- } +- } + if (dc->desc) { + error_printf(", desc \"%s\"", dc->desc); + } +@@ -105,15 +102,6 @@ static void qdev_print_class_devinfo(DeviceClass *dc) + error_printf("\n"); + } + +-static void qdev_print_devinfo(ObjectClass *klass, void *opaque) +-{ +- DeviceClass *dc; +- +- dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); +- +- qdev_print_class_devinfo(dc); +-} +- + static int set_property(const char *name, const char *value, void *opaque) + { + DeviceState *dev = opaque; +@@ -151,21 +139,6 @@ static const char *find_typename_by_alias(const char *alias) + return NULL; + } + +-static void qdev_print_category_devices(DeviceCategory category) +-{ +- DeviceClass *dc; +- GSList *list, *curr; +- +- list = object_class_get_list(TYPE_DEVICE, false); +- for (curr = list; curr; curr = g_slist_next(curr)) { +- dc = (DeviceClass *)object_class_dynamic_cast(curr->data, TYPE_DEVICE); +- if (!dc->no_user && test_bit(category, dc->categories)) { +- qdev_print_class_devinfo(dc); +- } +- } +- g_slist_free(list); +-} +- + int qdev_device_help(QemuOpts *opts) + { + const char *driver; +@@ -174,11 +147,8 @@ int qdev_device_help(QemuOpts *opts) + + driver = qemu_opt_get(opts, "driver"); + if (driver && is_help_option(driver)) { +- DeviceCategory category; +- for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) { +- qdev_print_category_devices(category); +- } +- ++ bool show_no_user = false; ++ object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user); + return 1; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-Preparation-for-usb-bt-dongle-conditional-build.patch b/SOURCES/kvm-Preparation-for-usb-bt-dongle-conditional-build.patch new file mode 100644 index 0000000..b6a3607 --- /dev/null +++ b/SOURCES/kvm-Preparation-for-usb-bt-dongle-conditional-build.patch @@ -0,0 +1,245 @@ +From bc5c67b27d0c1d8ec6c4d09352f0de6b6cbddad0 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Mon, 16 Sep 2013 14:38:24 +0200 +Subject: [PATCH 16/29] Preparation for usb-bt-dongle conditional build + +RH-Author: Miroslav Rezanina +Message-id: <0b3a39c76eac58a1b2f9f6c84016f234de0940c0.1379325610.git.mrezanin@redhat.com> +Patchwork-id: 54394 +O-Subject: [RHEL7 qemu-kvm PATCH 1/2] Preparation for usb-bt-dongle conditional build +Bugzilla: 1001131 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini + +From: Miroslav Rezanina + +To allow disable usb-bt-dongle device using CONFIG_BLUETOOTH option, some of +functions in vl.c file has to be made accessible in dev-bluetooth.c. This is +pure code moving. + +Signed-off-by: Miroslav Rezanina +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 644e1a8a34d2f799bfeefae94b71593a2aa662ae) +--- + hw/bt/core.c | 23 +++++++++++++++++++ + hw/bt/hci.c | 48 +++++++++++++++++++++++++++++++++++++++ + include/hw/bt.h | 3 +++ + vl.c | 69 --------------------------------------------------------- + 4 files changed, 74 insertions(+), 69 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/bt/core.c | 23 ++++++++++++++++++ + hw/bt/hci.c | 48 ++++++++++++++++++++++++++++++++++++++ + include/hw/bt.h | 3 ++ + vl.c | 69 ------------------------------------------------------- + 4 files changed, 74 insertions(+), 69 deletions(-) + +diff --git a/hw/bt/core.c b/hw/bt/core.c +index 49012e0..0ffc948 100644 +--- a/hw/bt/core.c ++++ b/hw/bt/core.c +@@ -119,3 +119,26 @@ void bt_device_done(struct bt_device_s *dev) + + *p = dev->next; + } ++ ++static struct bt_vlan_s { ++ struct bt_scatternet_s net; ++ int id; ++ struct bt_vlan_s *next; ++} *first_bt_vlan; ++ ++/* find or alloc a new bluetooth "VLAN" */ ++struct bt_scatternet_s *qemu_find_bt_vlan(int id) ++{ ++ struct bt_vlan_s **pvlan, *vlan; ++ for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) { ++ if (vlan->id == id) ++ return &vlan->net; ++ } ++ vlan = g_malloc0(sizeof(struct bt_vlan_s)); ++ vlan->id = id; ++ pvlan = &first_bt_vlan; ++ while (*pvlan != NULL) ++ pvlan = &(*pvlan)->next; ++ *pvlan = vlan; ++ return &vlan->net; ++} +diff --git a/hw/bt/hci.c b/hw/bt/hci.c +index b53cd5d..64e1745 100644 +--- a/hw/bt/hci.c ++++ b/hw/bt/hci.c +@@ -429,6 +429,24 @@ static const uint8_t bt_event_reserved_mask[8] = { + 0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00, + }; + ++ ++static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) ++{ ++} ++ ++static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr) ++{ ++ return -ENOTSUP; ++} ++ ++struct HCIInfo null_hci = { ++ .cmd_send = null_hci_send, ++ .sco_send = null_hci_send, ++ .acl_send = null_hci_send, ++ .bdaddr_set = null_hci_addr_set, ++}; ++ ++ + static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci, + int evt, int len) + { +@@ -2176,6 +2194,36 @@ struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net) + return &s->info; + } + ++struct HCIInfo *hci_init(const char *str) ++{ ++ char *endp; ++ struct bt_scatternet_s *vlan = 0; ++ ++ if (!strcmp(str, "null")) ++ /* null */ ++ return &null_hci; ++ else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) ++ /* host[:hciN] */ ++ return bt_host_hci(str[4] ? str + 5 : "hci0"); ++ else if (!strncmp(str, "hci", 3)) { ++ /* hci[,vlan=n] */ ++ if (str[3]) { ++ if (!strncmp(str + 3, ",vlan=", 6)) { ++ vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); ++ if (*endp) ++ vlan = 0; ++ } ++ } else ++ vlan = qemu_find_bt_vlan(0); ++ if (vlan) ++ return bt_new_hci(vlan); ++ } ++ ++ fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); ++ ++ return 0; ++} ++ + static void bt_hci_done(struct HCIInfo *info) + { + struct bt_hci_s *hci = hci_from_info(info); +diff --git a/include/hw/bt.h b/include/hw/bt.h +index 830af94..49a9d03 100644 +--- a/include/hw/bt.h ++++ b/include/hw/bt.h +@@ -108,12 +108,15 @@ struct bt_device_s { + uint16_t clkoff; /* Note: Always little-endian */ + }; + ++extern struct HCIInfo null_hci; + /* bt.c */ + void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net); + void bt_device_done(struct bt_device_s *dev); ++struct bt_scatternet_s *qemu_find_bt_vlan(int id); + + /* bt-hci.c */ + struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net); ++struct HCIInfo *hci_init(const char *str); + + /* bt-vhci.c */ + void bt_vhci_init(struct HCIInfo *info); +diff --git a/vl.c b/vl.c +index 24536b5..d022f50 100644 +--- a/vl.c ++++ b/vl.c +@@ -844,45 +844,6 @@ static int nb_hcis; + static int cur_hci; + static struct HCIInfo *hci_table[MAX_NICS]; + +-static struct bt_vlan_s { +- struct bt_scatternet_s net; +- int id; +- struct bt_vlan_s *next; +-} *first_bt_vlan; +- +-/* find or alloc a new bluetooth "VLAN" */ +-static struct bt_scatternet_s *qemu_find_bt_vlan(int id) +-{ +- struct bt_vlan_s **pvlan, *vlan; +- for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) { +- if (vlan->id == id) +- return &vlan->net; +- } +- vlan = g_malloc0(sizeof(struct bt_vlan_s)); +- vlan->id = id; +- pvlan = &first_bt_vlan; +- while (*pvlan != NULL) +- pvlan = &(*pvlan)->next; +- *pvlan = vlan; +- return &vlan->net; +-} +- +-static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) +-{ +-} +- +-static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr) +-{ +- return -ENOTSUP; +-} +- +-static struct HCIInfo null_hci = { +- .cmd_send = null_hci_send, +- .sco_send = null_hci_send, +- .acl_send = null_hci_send, +- .bdaddr_set = null_hci_addr_set, +-}; +- + struct HCIInfo *qemu_next_hci(void) + { + if (cur_hci == nb_hcis) +@@ -891,36 +852,6 @@ struct HCIInfo *qemu_next_hci(void) + return hci_table[cur_hci++]; + } + +-static struct HCIInfo *hci_init(const char *str) +-{ +- char *endp; +- struct bt_scatternet_s *vlan = 0; +- +- if (!strcmp(str, "null")) +- /* null */ +- return &null_hci; +- else if (!strncmp(str, "host", 4) && (str[4] == '\0' || str[4] == ':')) +- /* host[:hciN] */ +- return bt_host_hci(str[4] ? str + 5 : "hci0"); +- else if (!strncmp(str, "hci", 3)) { +- /* hci[,vlan=n] */ +- if (str[3]) { +- if (!strncmp(str + 3, ",vlan=", 6)) { +- vlan = qemu_find_bt_vlan(strtol(str + 9, &endp, 0)); +- if (*endp) +- vlan = 0; +- } +- } else +- vlan = qemu_find_bt_vlan(0); +- if (vlan) +- return bt_new_hci(vlan); +- } +- +- fprintf(stderr, "qemu: Unknown bluetooth HCI `%s'.\n", str); +- +- return 0; +-} +- + static int bt_hci_parse(const char *str) + { + struct HCIInfo *hci; +-- +1.7.1 + diff --git a/SOURCES/kvm-QemuOpts-Add-qemu_opt_unset.patch b/SOURCES/kvm-QemuOpts-Add-qemu_opt_unset.patch new file mode 100644 index 0000000..b210c8a --- /dev/null +++ b/SOURCES/kvm-QemuOpts-Add-qemu_opt_unset.patch @@ -0,0 +1,72 @@ +From 1201a6e29a7f8359588a3b635acbe12697325e66 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:18 +0200 +Subject: [PATCH 27/38] QemuOpts: Add qemu_opt_unset() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-28-git-send-email-kwolf@redhat.com> +Patchwork-id: 54214 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 27/32] QemuOpts: Add qemu_opt_unset() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 0dd6c5266313c861cf36476da86599d368ec41fc) + +Signed-off-by: Kevin Wolf +--- + include/qemu/option.h | 1 + + util/qemu-option.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + include/qemu/option.h | 1 + + util/qemu-option.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+), 0 deletions(-) + +diff --git a/include/qemu/option.h b/include/qemu/option.h +index bdb6d21..9db74fb 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -122,6 +122,7 @@ bool qemu_opt_has_help_opt(QemuOpts *opts); + bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval); + uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval); + uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval); ++int qemu_opt_unset(QemuOpts *opts, const char *name); + int qemu_opt_set(QemuOpts *opts, const char *name, const char *value); + void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value, + Error **errp); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index bdfbdb4..37e7640 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -623,6 +623,20 @@ static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc, + return NULL; + } + ++int qemu_opt_unset(QemuOpts *opts, const char *name) ++{ ++ QemuOpt *opt = qemu_opt_find(opts, name); ++ ++ assert(opts_accepts_any(opts)); ++ ++ if (opt == NULL) { ++ return -1; ++ } else { ++ qemu_opt_del(opt); ++ return 0; ++ } ++} ++ + static void opt_set(QemuOpts *opts, const char *name, const char *value, + bool prepend, Error **errp) + { +-- +1.7.1 + diff --git a/SOURCES/kvm-Remove-dev-bluetooth.c-dependency-from-vl.c.patch b/SOURCES/kvm-Remove-dev-bluetooth.c-dependency-from-vl.c.patch new file mode 100644 index 0000000..7dcfb0e --- /dev/null +++ b/SOURCES/kvm-Remove-dev-bluetooth.c-dependency-from-vl.c.patch @@ -0,0 +1,132 @@ +From d23a5d0e1d9a437515d566e29706e12373de9e25 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Mon, 16 Sep 2013 14:38:25 +0200 +Subject: [PATCH 17/29] Remove dev-bluetooth.c dependency from vl.c + +RH-Author: Miroslav Rezanina +Message-id: <1948c111aeb1ae630ad580f4805d57c35eccceef.1379325610.git.mrezanin@redhat.com> +Patchwork-id: 54395 +O-Subject: [RHEL7 qemu-kvm PATCH 2/2] Remove dev-bluetooth.c dependency from vl.c +Bugzilla: 1001131 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini + +From: Miroslav Rezanina + +Use usb_legacy_register handling to create bt-dongle device and remove code +dependency from vl.c so CONFIG_USB_BLUETOOTH can be disabled. + +Signed-off-by: Miroslav Rezanina +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 615fe4de4b3c26619611078960d3103550bde7d0) +--- + hw/usb/Makefile.objs | 3 --- + hw/usb/dev-bluetooth.c | 10 +++++++++- + include/hw/usb.h | 3 --- + vl.c | 13 ++++--------- + 4 files changed, 13 insertions(+), 16 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/Makefile.objs | 3 --- + hw/usb/dev-bluetooth.c | 10 +++++++++- + include/hw/usb.h | 3 --- + vl.c | 13 ++++--------- + 4 files changed, 13 insertions(+), 16 deletions(-) + +diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs +index f9695e7..a3eac3e 100644 +--- a/hw/usb/Makefile.objs ++++ b/hw/usb/Makefile.objs +@@ -18,9 +18,6 @@ common-obj-$(CONFIG_USB_STORAGE_UAS) += dev-uas.o + common-obj-$(CONFIG_USB_AUDIO) += dev-audio.o + common-obj-$(CONFIG_USB_SERIAL) += dev-serial.o + common-obj-$(CONFIG_USB_NETWORK) += dev-network.o +- +-# FIXME: make configurable too +-CONFIG_USB_BLUETOOTH := y + common-obj-$(CONFIG_USB_BLUETOOTH) += dev-bluetooth.o + + ifeq ($(CONFIG_USB_SMARTCARD),y) +diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c +index 68cc1d4..786e30e 100644 +--- a/hw/usb/dev-bluetooth.c ++++ b/hw/usb/dev-bluetooth.c +@@ -511,10 +511,17 @@ static int usb_bt_initfn(USBDevice *dev) + return 0; + } + +-USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci) ++static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline) + { + USBDevice *dev; + struct USBBtState *s; ++ HCIInfo *hci; ++ ++ if (*cmdline) { ++ hci = hci_init(cmdline); ++ } else { ++ hci = bt_new_hci(qemu_find_bt_vlan(0)); ++ } + + if (!hci) + return NULL; +@@ -565,6 +572,7 @@ static const TypeInfo bt_info = { + static void usb_bt_register_types(void) + { + type_register_static(&bt_info); ++ usb_legacy_register("usb-bt-dongle", "bt", usb_bt_init); + } + + type_init(usb_bt_register_types) +diff --git a/include/hw/usb.h b/include/hw/usb.h +index 901b0da..695d853 100644 +--- a/include/hw/usb.h ++++ b/include/hw/usb.h +@@ -442,9 +442,6 @@ int set_usb_string(uint8_t *buf, const char *str); + USBDevice *usb_host_device_open(USBBus *bus, const char *devname); + void usb_host_info(Monitor *mon, const QDict *qdict); + +-/* usb-bt.c */ +-USBDevice *usb_bt_init(USBBus *bus, HCIInfo *hci); +- + /* usb ports of the VM */ + + #define VM_USB_HUB_SIZE 8 +diff --git a/vl.c b/vl.c +index d022f50..a40ab13 100644 +--- a/vl.c ++++ b/vl.c +@@ -1427,8 +1427,10 @@ static void configure_msg(QemuOpts *opts) + + static int usb_device_add(const char *devname) + { +- const char *p; + USBDevice *dev = NULL; ++#ifndef CONFIG_LINUX ++ const char *p; ++#endif + + if (!usb_enabled(false)) { + return -1; +@@ -1444,15 +1446,8 @@ static int usb_device_add(const char *devname) + /* only the linux version is qdev-ified, usb-bsd still needs this */ + if (strstart(devname, "host:", &p)) { + dev = usb_host_device_open(usb_bus_find(-1), p); +- } else +-#endif +- if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) { +- dev = usb_bt_init(usb_bus_find(-1), +- devname[2] ? hci_init(p) +- : bt_new_hci(qemu_find_bt_vlan(0))); +- } else { +- return -1; + } ++#endif + if (!dev) + return -1; + +-- +1.7.1 + diff --git a/SOURCES/kvm-Remove-i82550-network-card-emulation.patch b/SOURCES/kvm-Remove-i82550-network-card-emulation.patch new file mode 100644 index 0000000..531a200 --- /dev/null +++ b/SOURCES/kvm-Remove-i82550-network-card-emulation.patch @@ -0,0 +1,47 @@ +From b42cc9467d522246bec3d9abc6e820c9e8f68743 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Fri, 30 Aug 2013 08:51:21 +0200 +Subject: [PATCH 02/29] Remove i82550 network card emulation + +RH-Author: Miroslav Rezanina +Message-id: <8a443ebad7bda82e3a609db476db3f77b97dab53.1377851454.git.mrezanin@redhat.com> +Patchwork-id: 53933 +O-Subject: [RHEL7 qemu-kvm PATCHv2 1/6] Remove i82550 network card emulation +Bugzilla: 921983 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +Bugzilla: 921983 +Upstream: n/a, RHEL only + +We do not support i82550 card and it's variants. Removing the card +from configuration. + +Signed-off-by: Miroslav Rezanina +--- + default-configs/pci.mak | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/pci.mak | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/default-configs/pci.mak b/default-configs/pci.mak +index c0fb0ae..938f413 100644 +--- a/default-configs/pci.mak ++++ b/default-configs/pci.mak +@@ -4,7 +4,6 @@ CONFIG_VIRTIO=y + CONFIG_USB_UHCI=y + CONFIG_USB_EHCI=y + CONFIG_USB_XHCI=y +-CONFIG_EEPRO100_PCI=y + CONFIG_AC97=y + CONFIG_HDA=y + CONFIG_RTL8139_PCI=y +-- +1.7.1 + diff --git a/SOURCES/kvm-Remove-no-hpet-option.patch b/SOURCES/kvm-Remove-no-hpet-option.patch new file mode 100644 index 0000000..84f51f6 --- /dev/null +++ b/SOURCES/kvm-Remove-no-hpet-option.patch @@ -0,0 +1,89 @@ +From 6a547c27c5d359af376fdb277ea05eea0d76e870 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Fri, 30 Aug 2013 08:51:25 +0200 +Subject: [PATCH 06/29] Remove no-hpet option + +RH-Author: Miroslav Rezanina +Message-id: <9d2bbee5227f35ee23da66a8689a9cd0faf545f1.1377851454.git.mrezanin@redhat.com> +Patchwork-id: 53936 +O-Subject: [RHEL7 qemu-kvm PATCHv2 5/6] Remove no-hpet option +Bugzilla: 947441 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +Bugzilla: 947441 +Upstream: n/a, RHEL only + +We disable HPET for RHEL, this patch removes option no-hpet that is +not usable. + +Patch is forwardport of RHEL6 patch 1c07ac51 with small difference in +qemu-options.hx STEXI part of no-hpet is removed to keep man page +updated. + +Signed-off-by: Miroslav Rezanina + +v2: + - Remove only STEXI part +--- + qemu-options.hx | 7 ++----- + vl.c | 4 +++- + 2 files changed, 5 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-options.hx | 7 ++----- + vl.c | 4 +++- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index 2ad0ed2..202a2cf 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -1283,13 +1283,10 @@ it if your guest OS complains about ACPI problems (PC target machine + only). + ETEXI + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + DEF("no-hpet", 0, QEMU_OPTION_no_hpet, + "-no-hpet disable HPET\n", QEMU_ARCH_I386) +-STEXI +-@item -no-hpet +-@findex -no-hpet +-Disable HPET support. +-ETEXI ++#endif + + DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable, + "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n" +diff --git a/vl.c b/vl.c +index f7b326a..24536b5 100644 +--- a/vl.c ++++ b/vl.c +@@ -217,7 +217,7 @@ int smp_threads = 1; + const char *vnc_display; + #endif + int acpi_enabled = 1; +-int no_hpet = 0; ++int no_hpet = 1; /* Always disabled for Red Hat Enterprise Linux */ + int fd_bootchk = 1; + static int no_reboot; + int no_shutdown = 0; +@@ -3682,9 +3682,11 @@ int main(int argc, char **argv, char **envp) + case QEMU_OPTION_no_acpi: + acpi_enabled = 0; + break; ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + case QEMU_OPTION_no_hpet: + no_hpet = 1; + break; ++#endif + case QEMU_OPTION_balloon: + if (balloon_parse(optarg) < 0) { + fprintf(stderr, "Unknown -balloon argument %s\n", optarg); +-- +1.7.1 + diff --git a/SOURCES/kvm-Remove-usb-wacom-tablet.patch b/SOURCES/kvm-Remove-usb-wacom-tablet.patch new file mode 100644 index 0000000..f8e5a85 --- /dev/null +++ b/SOURCES/kvm-Remove-usb-wacom-tablet.patch @@ -0,0 +1,44 @@ +From 03abc329e1bc5b54945113f55bddf3ef95974bb2 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Fri, 30 Aug 2013 08:51:22 +0200 +Subject: [PATCH 03/29] Remove usb wacom tablet + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 53935 +O-Subject: [RHEL7 qemu-kvm PATCHv2 2/6] Remove usb wacom tablet +Bugzilla: 903914 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +BZ: 903914 +Upstream: n/a, RHEL only + +We do not support wacom tablet, disabling it. + +Signed-off-by: Miroslav Rezanina +--- + default-configs/usb.mak | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/usb.mak | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/default-configs/usb.mak b/default-configs/usb.mak +index 9a3bd09..39a3552 100644 +--- a/default-configs/usb.mak ++++ b/default-configs/usb.mak +@@ -1,4 +1,3 @@ +-CONFIG_USB_TABLET_WACOM=y + CONFIG_USB_STORAGE_BOT=y + CONFIG_USB_STORAGE_UAS=y + CONFIG_USB_SMARTCARD=y +-- +1.7.1 + diff --git a/SOURCES/kvm-Revert-block-Disable-driver-specific-options-for-1.5.patch b/SOURCES/kvm-Revert-block-Disable-driver-specific-options-for-1.5.patch new file mode 100644 index 0000000..982fa7c --- /dev/null +++ b/SOURCES/kvm-Revert-block-Disable-driver-specific-options-for-1.5.patch @@ -0,0 +1,178 @@ +From 2f216971132c8fd7a6b05af6efa8103b9459b7f5 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:59 +0200 +Subject: [PATCH 08/38] Revert "block: Disable driver-specific options for 1.5" + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-9-git-send-email-kwolf@redhat.com> +Patchwork-id: 54197 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 08/32] Revert "block: Disable driver-specific options for 1.5" +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This reverts commit 8ec7d390b0d50b5e5b4b1d8dba7ba40d64a70875. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 492fdc6fbe17b2d45878e813e980f782ac260c30) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 118 ++--------------------------------------------- + tests/qemu-iotests/group | 2 +- + 2 files changed, 5 insertions(+), 115 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 118 ++-------------------------------------------- + tests/qemu-iotests/group | 2 +- + 2 files changed, 5 insertions(+), 115 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 1f405c9..bd33c17 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -1719,120 +1719,10 @@ QemuOptsList qemu_drive_opts = { + .name = "drive", + .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head), + .desc = { +- { +- .name = "bus", +- .type = QEMU_OPT_NUMBER, +- .help = "bus number", +- },{ +- .name = "unit", +- .type = QEMU_OPT_NUMBER, +- .help = "unit number (i.e. lun for scsi)", +- },{ +- .name = "if", +- .type = QEMU_OPT_STRING, +- .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +- },{ +- .name = "index", +- .type = QEMU_OPT_NUMBER, +- .help = "index number", +- },{ +- .name = "cyls", +- .type = QEMU_OPT_NUMBER, +- .help = "number of cylinders (ide disk geometry)", +- },{ +- .name = "heads", +- .type = QEMU_OPT_NUMBER, +- .help = "number of heads (ide disk geometry)", +- },{ +- .name = "secs", +- .type = QEMU_OPT_NUMBER, +- .help = "number of sectors (ide disk geometry)", +- },{ +- .name = "trans", +- .type = QEMU_OPT_STRING, +- .help = "chs translation (auto, lba. none)", +- },{ +- .name = "media", +- .type = QEMU_OPT_STRING, +- .help = "media type (disk, cdrom)", +- },{ +- .name = "snapshot", +- .type = QEMU_OPT_BOOL, +- .help = "enable/disable snapshot mode", +- },{ +- .name = "file", +- .type = QEMU_OPT_STRING, +- .help = "disk image", +- },{ +- .name = "discard", +- .type = QEMU_OPT_STRING, +- .help = "discard operation (ignore/off, unmap/on)", +- },{ +- .name = "cache", +- .type = QEMU_OPT_STRING, +- .help = "host cache usage (none, writeback, writethrough, " +- "directsync, unsafe)", +- },{ +- .name = "aio", +- .type = QEMU_OPT_STRING, +- .help = "host AIO implementation (threads, native)", +- },{ +- .name = "format", +- .type = QEMU_OPT_STRING, +- .help = "disk format (raw, qcow2, ...)", +- },{ +- .name = "serial", +- .type = QEMU_OPT_STRING, +- .help = "disk serial number", +- },{ +- .name = "rerror", +- .type = QEMU_OPT_STRING, +- .help = "read error action", +- },{ +- .name = "werror", +- .type = QEMU_OPT_STRING, +- .help = "write error action", +- },{ +- .name = "addr", +- .type = QEMU_OPT_STRING, +- .help = "pci address (virtio only)", +- },{ +- .name = "readonly", +- .type = QEMU_OPT_BOOL, +- .help = "open drive file as read-only", +- },{ +- .name = "iops", +- .type = QEMU_OPT_NUMBER, +- .help = "limit total I/O operations per second", +- },{ +- .name = "iops_rd", +- .type = QEMU_OPT_NUMBER, +- .help = "limit read operations per second", +- },{ +- .name = "iops_wr", +- .type = QEMU_OPT_NUMBER, +- .help = "limit write operations per second", +- },{ +- .name = "bps", +- .type = QEMU_OPT_NUMBER, +- .help = "limit total bytes per second", +- },{ +- .name = "bps_rd", +- .type = QEMU_OPT_NUMBER, +- .help = "limit read bytes per second", +- },{ +- .name = "bps_wr", +- .type = QEMU_OPT_NUMBER, +- .help = "limit write bytes per second", +- },{ +- .name = "copy-on-read", +- .type = QEMU_OPT_BOOL, +- .help = "copy read data from backing file into image file", +- },{ +- .name = "boot", +- .type = QEMU_OPT_BOOL, +- .help = "(deprecated, ignored)", +- }, ++ /* ++ * no elements => accept any params ++ * validation will happen later ++ */ + { /* end of list */ } + }, + }; +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index bf944d9..68eabda 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -57,6 +57,6 @@ + 048 img auto quick + 049 rw auto + 050 rw auto backing quick +-#051 rw auto ++051 rw auto + 052 rw auto backing + 053 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-Revert-usb-hub-report-status-changes-only-once.patch b/SOURCES/kvm-Revert-usb-hub-report-status-changes-only-once.patch new file mode 100644 index 0000000..70cc65f --- /dev/null +++ b/SOURCES/kvm-Revert-usb-hub-report-status-changes-only-once.patch @@ -0,0 +1,67 @@ +From 0808f68d525eca6d44f2f4660c34d953a36ae486 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 12 Sep 2013 09:39:32 +0200 +Subject: [PATCH 04/25] Revert "usb-hub: report status changes only once" + +RH-Author: Gerd Hoffmann +Message-id: <1378978772-21612-5-git-send-email-kraxel@redhat.com> +Patchwork-id: 54340 +O-Subject: [RHEL-7 qemu-kvm PATCH 4/4] Revert "usb-hub: report status changes only once" +Bugzilla: 1001604 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Hans de Goede +RH-Acked-by: Miroslav Rezanina + +This reverts commit a309ee6e0a256f690760abfba44fceaa52a7c2f3. + +This isn't in line with the usb specification and adds regressions, +win7 fails to drive the usb hub for example. + +Was added because it "solved" the issue of hubs interacting badly +with the xhci host controller. Now with the root cause being fixed +in xhci (commit ) we can revert this one. + +[ rhel7 note: Damn, forgot to fill in the final commit hash before + sending out the upstream pull request. It's commit + 4d7a81c06f5f17e019a2d3a18300500bd64f6f40 ] + +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit bdebd6ee81f4d849aa8541c289203e3992450db0) +--- + hw/usb/dev-hub.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/dev-hub.c | 6 +----- + 1 files changed, 1 insertions(+), 5 deletions(-) + +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index 0b71abd..a5f092b 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -33,7 +33,6 @@ typedef struct USBHubPort { + USBPort port; + uint16_t wPortStatus; + uint16_t wPortChange; +- uint16_t wPortChange_reported; + } USBHubPort; + + typedef struct USBHubState { +@@ -468,11 +467,8 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) + status = 0; + for(i = 0; i < NUM_PORTS; i++) { + port = &s->ports[i]; +- if (port->wPortChange && +- port->wPortChange_reported != port->wPortChange) { ++ if (port->wPortChange) + status |= (1 << (i + 1)); +- } +- port->wPortChange_reported = port->wPortChange; + } + if (status != 0) { + for(i = 0; i < n; i++) { +-- +1.7.1 + diff --git a/SOURCES/kvm-Simplify-machine-option-queries-with-qemu_get_machin.patch b/SOURCES/kvm-Simplify-machine-option-queries-with-qemu_get_machin.patch new file mode 100644 index 0000000..af0bc4a --- /dev/null +++ b/SOURCES/kvm-Simplify-machine-option-queries-with-qemu_get_machin.patch @@ -0,0 +1,283 @@ +From cfb7a42b4241cf1a8dea0f33947c66671923f694 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:05 +0200 +Subject: [PATCH 12/28] Simplify -machine option queries with qemu_get_machine_opts() + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-7-git-send-email-armbru@redhat.com> +Patchwork-id: 52996 +O-Subject: [PATCH 7.0 qemu-kvm 6/6] Simplify -machine option queries with qemu_get_machine_opts() +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +The previous two commits fixed bugs in -machine option queries. I +can't find fault with the remaining queries, but let's use +qemu_get_machine_opts() everywhere, for consistency, simplicity and +robustness. + +Signed-off-by: Markus Armbruster +Message-id: 1372943363-24081-7-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 2ff3de685a875ece3ee21256736c0a9dbf39dc4c) +--- + device_tree.c | 28 ++++++++++------------------ + exec.c | 12 ++++-------- + hw/arm/boot.c | 8 +------- + hw/ppc/e500.c | 12 +++--------- + hw/ppc/spapr.c | 28 ++++++++++------------------ + vl.c | 22 ++++++---------------- + 6 files changed, 34 insertions(+), 76 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + device_tree.c | 28 ++++++++++------------------ + exec.c | 12 ++++-------- + hw/arm/boot.c | 8 +------- + hw/ppc/e500.c | 12 +++--------- + hw/ppc/spapr.c | 28 ++++++++++------------------ + vl.c | 22 ++++++---------------- + 6 files changed, 34 insertions(+), 76 deletions(-) + +diff --git a/device_tree.c b/device_tree.c +index 56af24b..77cbe04 100644 +--- a/device_tree.c ++++ b/device_tree.c +@@ -21,6 +21,7 @@ + #include "config.h" + #include "qemu-common.h" + #include "sysemu/device_tree.h" ++#include "sysemu/sysemu.h" + #include "hw/loader.h" + #include "qemu/option.h" + #include "qemu/config-file.h" +@@ -239,14 +240,10 @@ uint32_t qemu_devtree_alloc_phandle(void *fdt) + * which phandle id to start allocting phandles. + */ + if (!phandle) { +- QemuOpts *machine_opts; +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- const char *phandle_start; +- phandle_start = qemu_opt_get(machine_opts, "phandle_start"); +- if (phandle_start) { +- phandle = strtoul(phandle_start, NULL, 0); +- } ++ const char *phandle_start = qemu_opt_get(qemu_get_machine_opts(), ++ "phandle_start"); ++ if (phandle_start) { ++ phandle = strtoul(phandle_start, NULL, 0); + } + } + +@@ -307,15 +304,10 @@ int qemu_devtree_add_subnode(void *fdt, const char *name) + + void qemu_devtree_dumpdtb(void *fdt, int size) + { +- QemuOpts *machine_opts; +- +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); +- if (dumpdtb) { +- /* Dump the dtb to a file and quit */ +- exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1); +- } +- } ++ const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); + ++ if (dumpdtb) { ++ /* Dump the dtb to a file and quit */ ++ exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1); ++ } + } +diff --git a/exec.c b/exec.c +index aec65c5..ee22b9b 100644 +--- a/exec.c ++++ b/exec.c +@@ -31,6 +31,7 @@ + #include "hw/qdev.h" + #include "qemu/osdep.h" + #include "sysemu/kvm.h" ++#include "sysemu/sysemu.h" + #include "hw/xen/xen.h" + #include "qemu/timer.h" + #include "qemu/config-file.h" +@@ -979,12 +980,10 @@ ram_addr_t last_ram_offset(void) + static void qemu_ram_setup_dump(void *addr, ram_addr_t size) + { + int ret; +- QemuOpts *machine_opts; + + /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */ +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts && +- !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) { ++ if (!qemu_opt_get_bool(qemu_get_machine_opts(), ++ "dump-guest-core", true)) { + ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP); + if (ret) { + perror("qemu_madvise"); +@@ -1031,10 +1030,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) + + static int memory_try_enable_merging(void *addr, size_t len) + { +- QemuOpts *opts; +- +- opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) { ++ if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) { + /* disabled by the user */ + return 0; + } +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index 6bffc3d..6436109 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -365,7 +365,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) + uint64_t elf_entry; + hwaddr entry; + int big_endian; +- QemuOpts *machine_opts; + + /* Load the kernel. */ + if (!info->kernel_filename) { +@@ -373,12 +372,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) + exit(1); + } + +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- info->dtb_filename = qemu_opt_get(machine_opts, "dtb"); +- } else { +- info->dtb_filename = NULL; +- } ++ info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + + if (!info->secondary_cpu_reset_hook) { + info->secondary_cpu_reset_hook = default_reset_secondary; +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index c9ae512..ef3e571 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -137,7 +137,6 @@ static int ppce500_load_device_tree(CPUPPCState *env, + uint32_t clock_freq = 400000000; + uint32_t tb_freq = 400000000; + int i; +- const char *toplevel_compat = NULL; /* user override */ + char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; + char soc[128]; + char mpic[128]; +@@ -158,14 +157,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, + 0x0, 0xe1000000, + 0x0, 0x10000, + }; +- QemuOpts *machine_opts; +- const char *dtb_file = NULL; +- +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- dtb_file = qemu_opt_get(machine_opts, "dtb"); +- toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); +- } ++ QemuOpts *machine_opts = qemu_get_machine_opts(); ++ const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); ++ const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); + + if (dtb_file) { + char *filename; +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c96ac81..6a46488 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -678,27 +678,19 @@ static void spapr_cpu_reset(void *opaque) + + static void spapr_create_nvram(sPAPREnvironment *spapr) + { +- QemuOpts *machine_opts; +- DeviceState *dev; ++ DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); ++ const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram"); + +- dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); ++ if (drivename) { ++ BlockDriverState *bs; + +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- const char *drivename; +- +- drivename = qemu_opt_get(machine_opts, "nvram"); +- if (drivename) { +- BlockDriverState *bs; +- +- bs = bdrv_find(drivename); +- if (!bs) { +- fprintf(stderr, "No such block device \"%s\" for nvram\n", +- drivename); +- exit(1); +- } +- qdev_prop_set_drive_nofail(dev, "drive", bs); ++ bs = bdrv_find(drivename); ++ if (!bs) { ++ fprintf(stderr, "No such block device \"%s\" for nvram\n", ++ drivename); ++ exit(1); + } ++ qdev_prop_set_drive_nofail(dev, "drive", bs); + } + + qdev_init_nofail(dev); +diff --git a/vl.c b/vl.c +index 0ed9257..d424af7 100644 +--- a/vl.c ++++ b/vl.c +@@ -1037,15 +1037,9 @@ static int parse_sandbox(QemuOpts *opts, void *opaque) + return 0; + } + +-/*********QEMU USB setting******/ + bool usb_enabled(bool default_usb) + { +- QemuOpts *mach_opts; +- mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (mach_opts) { +- return qemu_opt_get_bool(mach_opts, "usb", default_usb); +- } +- return default_usb; ++ return qemu_opt_get_bool(qemu_get_machine_opts(), "usb", default_usb); + } + + #ifndef _WIN32 +@@ -4136,14 +4130,10 @@ int main(int argc, char **argv, char **envp) + qtest_init(); + } + +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- kernel_filename = qemu_opt_get(machine_opts, "kernel"); +- initrd_filename = qemu_opt_get(machine_opts, "initrd"); +- kernel_cmdline = qemu_opt_get(machine_opts, "append"); +- } else { +- kernel_filename = initrd_filename = kernel_cmdline = NULL; +- } ++ machine_opts = qemu_get_machine_opts(); ++ kernel_filename = qemu_opt_get(machine_opts, "kernel"); ++ initrd_filename = qemu_opt_get(machine_opts, "initrd"); ++ kernel_cmdline = qemu_opt_get(machine_opts, "append"); + + if (!kernel_cmdline) { + kernel_cmdline = ""; +@@ -4161,7 +4151,7 @@ int main(int argc, char **argv, char **envp) + exit(1); + } + +- if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) { ++ if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) { + fprintf(stderr, "-dtb only allowed with -kernel option\n"); + exit(1); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-acpi-piix4-Enable-qemu-kvm-compatibility-mode.patch b/SOURCES/kvm-acpi-piix4-Enable-qemu-kvm-compatibility-mode.patch new file mode 100644 index 0000000..2ba1c91 --- /dev/null +++ b/SOURCES/kvm-acpi-piix4-Enable-qemu-kvm-compatibility-mode.patch @@ -0,0 +1,62 @@ +From 27aa81d0b84f03223414eb2e85b7fae0e0d2b86b Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Wed, 16 Oct 2013 13:07:15 +0200 +Subject: [PATCH 17/18] acpi/piix4: Enable qemu-kvm compatibility mode + +RH-Author: Eduardo Habkost +Message-id: <1381928835-10190-1-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54961 +O-Subject: [qemu-kvm RHEL-7 PATCH] acpi/piix4: Enable qemu-kvm compatibility mode +Bugzilla: 1019474 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Orit Wasserman +RH-Acked-by: Igor Mammedov + +Bugzilla: 1019474 +Scratch build: https://brewweb.devel.redhat.com/taskinfo?taskID=6426533 +Upstream status: not applicable + +>From the code comments: + + qemu-kvm 1.2 uses version 3 but advertised as 2 + To support incoming qemu-kvm 1.2 migration, change version_id + and minimum_version_id to 2 below (which breaks migration from + qemu 1.2). + +The v2 format of qemu-0.13 (implemented by upstream commit +4cf3e6f3d85492f20a773dd6c9068ab89ba24a18, and the one that was used on +qemu-kvm) is not compatible with the v2 format of qemu-0.15 and newer +(compatibility was broken by upstream commit +23910d3f669d46073b403876e30a7314599633af). RHEL-6 is using the former +format (RHEL-6 commit c4101c5340988caa68da87066a88d3871c8c4bf1), which +is not compatible with upstream QEMU. + +This sets minimum_version_id to 2, so we enable the qemu-kvm +compatibility mode, to allow us to load RHEL-6 migration data. + +Signed-off-by: Eduardo Habkost +--- + hw/acpi/piix4.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/acpi/piix4.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index 86ff598..f14867a 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -278,7 +278,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) + static const VMStateDescription vmstate_acpi = { + .name = "piix4_pm", + .version_id = 3, +- .minimum_version_id = 3, ++ .minimum_version_id = 2, + .minimum_version_id_old = 1, + .load_state_old = acpi_load_old, + .post_load = vmstate_acpi_post_load, +-- +1.7.1 + diff --git a/SOURCES/kvm-add-qemu-img-convert-n-option-skip-target-volume-cre.patch b/SOURCES/kvm-add-qemu-img-convert-n-option-skip-target-volume-cre.patch new file mode 100644 index 0000000..0d8f0eb --- /dev/null +++ b/SOURCES/kvm-add-qemu-img-convert-n-option-skip-target-volume-cre.patch @@ -0,0 +1,339 @@ +From f6e47d854362ee1f5d405852ac75f2015bf94ad7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 12:27:37 +0100 +Subject: [PATCH 15/87] add qemu-img convert -n option (skip target volume creation) + +RH-Author: Max Reitz +Message-id: <1383604354-12743-18-git-send-email-mreitz@redhat.com> +Patchwork-id: 55317 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 17/43] add qemu-img convert -n option (skip target volume creation) +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Alexandre Derumier + +BZ: 1026524 + +Add a -n option to skip volume creation on qemu-img convert. +This is useful for targets such as rbd / ceph, where the +target volume may already exist; we cannot always rely on +qemu-img convert to create the image, as dependent on the +output format, there may be parameters which are not possible +to specify through the qemu-img convert command line. + +Reviewed-by: Eric Blake +Signed-off-by: Alexandre Derumier +Signed-off-by: Alex Bligh +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit b2e10493c71160d88bb823cae9a92e806a79b9d6) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/group + +Conflicts because upstream contains more tests in the group file. +Signed-off-by: Miroslav Rezanina +--- + qemu-img-cmds.hx | 4 +- + qemu-img.c | 53 +++++++++++++++++------- + qemu-img.texi | 15 ++++++- + tests/qemu-iotests/063 | 97 ++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/063.out | 10 +++++ + tests/qemu-iotests/group | 1 + + 6 files changed, 162 insertions(+), 18 deletions(-) + create mode 100644 tests/qemu-iotests/063 + create mode 100644 tests/qemu-iotests/063.out + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index c97a1f4..0c36e59 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -34,9 +34,9 @@ STEXI + ETEXI + + DEF("convert", img_convert, +- "convert [-c] [-p] [-q] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename") ++ "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename") + STEXI +-@item convert [-c] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} + ETEXI + + DEF("info", img_info, +diff --git a/qemu-img.c b/qemu-img.c +index 3a59bf0..8fcea44 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -101,6 +101,8 @@ static void help(void) + " '-S' indicates the consecutive number of bytes that must contain only zeros\n" + " for qemu-img to create a sparse image during conversion\n" + " '--output' takes the format in which the output must be done (human or json)\n" ++ " '-n' skips the target volume creation (useful if the volume is created\n" ++ " prior to running qemu-img)\n" + "\n" + "Parameters to check subcommand:\n" + " '-r' tries to repair any inconsistencies that are found during the check.\n" +@@ -1113,7 +1115,8 @@ out3: + + static int img_convert(int argc, char **argv) + { +- int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors; ++ int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, ++ cluster_sectors, skip_create; + int progress = 0, flags; + const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename; + BlockDriver *drv, *proto_drv; +@@ -1136,8 +1139,9 @@ static int img_convert(int argc, char **argv) + cache = "unsafe"; + out_baseimg = NULL; + compress = 0; ++ skip_create = 0; + for(;;) { +- c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:q"); ++ c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qn"); + if (c == -1) { + break; + } +@@ -1194,6 +1198,9 @@ static int img_convert(int argc, char **argv) + case 'q': + quiet = true; + break; ++ case 'n': ++ skip_create = 1; ++ break; + } + } + +@@ -1326,20 +1333,22 @@ static int img_convert(int argc, char **argv) + } + } + +- /* Create the new image */ +- ret = bdrv_create(drv, out_filename, param); +- if (ret < 0) { +- if (ret == -ENOTSUP) { +- error_report("Formatting not supported for file format '%s'", +- out_fmt); +- } else if (ret == -EFBIG) { +- error_report("The image size is too large for file format '%s'", +- out_fmt); +- } else { +- error_report("%s: error while converting %s: %s", +- out_filename, out_fmt, strerror(-ret)); ++ if (!skip_create) { ++ /* Create the new image */ ++ ret = bdrv_create(drv, out_filename, param); ++ if (ret < 0) { ++ if (ret == -ENOTSUP) { ++ error_report("Formatting not supported for file format '%s'", ++ out_fmt); ++ } else if (ret == -EFBIG) { ++ error_report("The image size is too large for file format '%s'", ++ out_fmt); ++ } else { ++ error_report("%s: error while converting %s: %s", ++ out_filename, out_fmt, strerror(-ret)); ++ } ++ goto out; + } +- goto out; + } + + flags = BDRV_O_RDWR; +@@ -1360,6 +1369,20 @@ static int img_convert(int argc, char **argv) + bdrv_get_geometry(bs[0], &bs_sectors); + buf = qemu_blockalign(out_bs, IO_BUF_SIZE); + ++ if (skip_create) { ++ int64_t output_length = bdrv_getlength(out_bs); ++ if (output_length < 0) { ++ error_report("unable to get output image length: %s\n", ++ strerror(-output_length)); ++ ret = -1; ++ goto out; ++ } else if (output_length < total_sectors << BDRV_SECTOR_BITS) { ++ error_report("output file is smaller than input file"); ++ ret = -1; ++ goto out; ++ } ++ } ++ + if (compress) { + ret = bdrv_get_info(out_bs, &bdi); + if (ret < 0) { +diff --git a/qemu-img.texi b/qemu-img.texi +index 8364fa1..43ee4eb 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -96,6 +96,14 @@ Second image format + Strict mode - fail on on different image size or sector allocation + @end table + ++Parameters to convert subcommand: ++ ++@table @option ++ ++@item -n ++Skip the creation of the target volume ++@end table ++ + Command description: + + @table @option +@@ -171,7 +179,7 @@ Error on reading data + + @end table + +-@item convert [-c] [-p] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} ++@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} + + Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename} + using format @var{output_fmt}. It can be optionally compressed (@code{-c} +@@ -190,6 +198,11 @@ created as a copy on write image of the specified base image; the + @var{backing_file} should have the same content as the input's base image, + however the path, image format, etc may differ. + ++If the @code{-n} option is specified, the target volume creation will be ++skipped. This is useful for formats such as @code{rbd} if the target ++volume has already been created with site specific options that cannot ++be supplied through qemu-img. ++ + @item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} + + Give information about the disk image @var{filename}. Use it in +diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063 +new file mode 100644 +index 0000000..de0cbbd +--- /dev/null ++++ b/tests/qemu-iotests/063 +@@ -0,0 +1,97 @@ ++#!/bin/bash ++# ++# test of qemu-img convert -n - convert without creation ++# ++# Copyright (C) 2009 Red Hat, Inc. ++# Copyright (C) 2013 Alex Bligh (alex@alex.org.uk) ++# ++# 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=alex@alex.org.uk ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++here=`pwd` ++tmp=/tmp/$$ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++ rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2 ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++. ./common.pattern ++ ++_supported_fmt qcow qcow2 vmdk qed raw ++_supported_proto generic ++_supported_os Linux ++ ++_make_test_img 4M ++ ++echo "== Testing conversion with -n fails with no target file ==" ++# check .orig file does not exist ++rm -f $TEST_IMG.orig ++if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig >/dev/null 2>&1; then ++ exit 1 ++fi ++ ++echo "== Testing conversion with -n succeeds with a target file ==" ++rm -f $TEST_IMG.orig ++cp $TEST_IMG $TEST_IMG.orig ++if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig ; then ++ exit 1 ++fi ++ ++echo "== Testing conversion to raw is the same after conversion with -n ==" ++# compare the raw files ++if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG $TEST_IMG.raw1 ; then ++ exit 1 ++fi ++ ++if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG.orig $TEST_IMG.raw2 ; then ++ exit 1 ++fi ++ ++if ! cmp $TEST_IMG.raw1 $TEST_IMG.raw2 ; then ++ exit 1 ++fi ++ ++echo "== Testing conversion back to original format ==" ++if ! $QEMU_IMG convert -f raw -O $IMGFMT -n $TEST_IMG.raw2 $TEST_IMG ; then ++ exit 1 ++fi ++_check_test_img ++ ++echo "== Testing conversion to a smaller file fails ==" ++rm -f $TEST_IMG.orig ++mv $TEST_IMG $TEST_IMG.orig ++_make_test_img 2M ++if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG.orig $TEST_IMG >/dev/null 2>&1; then ++ exit 1 ++fi ++ ++rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2 ++ ++echo "*** done" ++rm -f $seq.full ++status=0 ++exit 0 +diff --git a/tests/qemu-iotests/063.out b/tests/qemu-iotests/063.out +new file mode 100644 +index 0000000..de1c99a +--- /dev/null ++++ b/tests/qemu-iotests/063.out +@@ -0,0 +1,10 @@ ++QA output created by 063 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4194304 ++== Testing conversion with -n fails with no target file == ++== Testing conversion with -n succeeds with a target file == ++== Testing conversion to raw is the same after conversion with -n == ++== Testing conversion back to original format == ++No errors were found on the image. ++== Testing conversion to a smaller file fails == ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2097152 ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 9c8826d..ff3c505 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -62,4 +62,5 @@ + 053 rw auto + 059 rw auto + 060 rw auto ++063 rw auto + 068 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-add-timestamp-to-error_report.patch b/SOURCES/kvm-add-timestamp-to-error_report.patch new file mode 100644 index 0000000..d1c75f8 --- /dev/null +++ b/SOURCES/kvm-add-timestamp-to-error_report.patch @@ -0,0 +1,182 @@ +From d654202a62b8bf07cba4044e4eb912958c7392bb Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 28 Aug 2013 15:50:44 +0200 +Subject: [PATCH 27/28] add timestamp to error_report() + +RH-Author: Laszlo Ersek +Message-id: <1377705045-1054-2-git-send-email-lersek@redhat.com> +Patchwork-id: 53886 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 1/2] add timestamp to error_report() +Bugzilla: 906937 +RH-Acked-by: Michal Novotny +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +From: Seiji Aguchi + +[Issue] +When we offer a customer support service and a problem happens +in a customer's system, we try to understand the problem by +comparing what the customer reports with message logs of the +customer's system. + +In this case, we often need to know when the problem happens. + +But, currently, there is no timestamp in qemu's error messages. +Therefore, we may not be able to understand the problem based on +error messages. + +[Solution] +Add a timestamp to qemu's error message logged by +error_report() with g_time_val_to_iso8601(). + +Signed-off-by: Seiji Aguchi +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Luiz Capitulino +(cherry picked from commit 5e2ac5191772dea782ff78e95edd395985273019) +Signed-off-by: Laszlo Ersek +--- + include/qemu/error-report.h | 2 ++ + util/qemu-error.c | 10 ++++++++++ + vl.c | 26 ++++++++++++++++++++++++++ + qemu-options.hx | 11 +++++++++++ + 4 files changed, 49 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/qemu/error-report.h | 2 ++ + qemu-options.hx | 11 +++++++++++ + util/qemu-error.c | 10 ++++++++++ + vl.c | 26 ++++++++++++++++++++++++++ + 4 files changed, 49 insertions(+), 0 deletions(-) + +diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h +index 14c1719..3b098a9 100644 +--- a/include/qemu/error-report.h ++++ b/include/qemu/error-report.h +@@ -14,6 +14,7 @@ + #define QEMU_ERROR_H + + #include ++#include + #include "qemu/compiler.h" + + typedef struct Location { +@@ -40,5 +41,6 @@ void error_print_loc(void); + void error_set_progname(const char *argv0); + void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); + const char *error_get_progname(void); ++extern bool enable_timestamp_msg; + + #endif +diff --git a/qemu-options.hx b/qemu-options.hx +index fb62b75..2ad0ed2 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -3095,6 +3095,17 @@ property must be set. These objects are placed in the + '/objects' path. + ETEXI + ++DEF("msg", HAS_ARG, QEMU_OPTION_msg, ++ "-msg timestamp[=on|off]\n" ++ " change the format of messages\n" ++ " on|off controls leading timestamps (default:on)\n", ++ QEMU_ARCH_ALL) ++STEXI ++@item -msg timestamp[=on|off] ++@findex -msg ++prepend a timestamp to each log message.(default:on) ++ETEXI ++ + HXCOMM This is the last statement. Insert new options before this line! + STEXI + @end table +diff --git a/util/qemu-error.c b/util/qemu-error.c +index 08a36f4..fec02c6 100644 +--- a/util/qemu-error.c ++++ b/util/qemu-error.c +@@ -196,6 +196,7 @@ void error_print_loc(void) + } + } + ++bool enable_timestamp_msg; + /* + * Print an error message to current monitor if we have one, else to stderr. + * Format arguments like sprintf(). The result should not contain +@@ -206,6 +207,15 @@ void error_print_loc(void) + void error_report(const char *fmt, ...) + { + va_list ap; ++ GTimeVal tv; ++ gchar *timestr; ++ ++ if (enable_timestamp_msg) { ++ g_get_current_time(&tv); ++ timestr = g_time_val_to_iso8601(&tv); ++ error_printf("%s ", timestr); ++ g_free(timestr); ++ } + + error_print_loc(); + va_start(ap, fmt); +diff --git a/vl.c b/vl.c +index d424af7..0ce554d 100644 +--- a/vl.c ++++ b/vl.c +@@ -518,6 +518,18 @@ static QemuOptsList qemu_realtime_opts = { + }, + }; + ++static QemuOptsList qemu_msg_opts = { ++ .name = "msg", ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_msg_opts.head), ++ .desc = { ++ { ++ .name = "timestamp", ++ .type = QEMU_OPT_BOOL, ++ }, ++ { /* end of list */ } ++ }, ++}; ++ + /** + * Get machine options + * +@@ -1473,6 +1485,12 @@ static void configure_realtime(QemuOpts *opts) + } + } + ++ ++static void configure_msg(QemuOpts *opts) ++{ ++ enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true); ++} ++ + /***********************************************************/ + /* USB devices */ + +@@ -2911,6 +2929,7 @@ int main(int argc, char **argv, char **envp) + qemu_add_opts(&qemu_object_opts); + qemu_add_opts(&qemu_tpmdev_opts); + qemu_add_opts(&qemu_realtime_opts); ++ qemu_add_opts(&qemu_msg_opts); + + runstate_init(); + +@@ -3883,6 +3902,13 @@ int main(int argc, char **argv, char **envp) + } + configure_realtime(opts); + break; ++ case QEMU_OPTION_msg: ++ opts = qemu_opts_parse(qemu_find_opts("msg"), optarg, 0); ++ if (!opts) { ++ exit(1); ++ } ++ configure_msg(opts); ++ break; + default: + os_parse_cmd_args(popt->index, optarg); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-all.c-max_cpus-should-not-exceed-KVM-vcpu-limit.patch b/SOURCES/kvm-all.c-max_cpus-should-not-exceed-KVM-vcpu-limit.patch new file mode 100644 index 0000000..8a7a2d2 --- /dev/null +++ b/SOURCES/kvm-all.c-max_cpus-should-not-exceed-KVM-vcpu-limit.patch @@ -0,0 +1,51 @@ +From fbbdbb9f62c7239d8e299b17be82e5ac3b5eca09 Mon Sep 17 00:00:00 2001 +From: Marcelo Tosatti +Date: Tue, 20 Aug 2013 21:45:54 +0200 +Subject: [PATCH 26/28] kvm-all.c: max_cpus should not exceed KVM vcpu limit + +RH-Author: Marcelo Tosatti +Message-id: <20130820214554.GB9334@amt.cnet> +Patchwork-id: 53621 +O-Subject: [RHEL7 qemu-kvm PATCH] kvm-all.c: max_cpus should not exceed KVM vcpu limit +Bugzilla: 996258 +RH-Acked-by: Andrew Jones +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Eduardo Habkost + +commit 7dc52526850849e8e0fe56ced809d0798481a2f6 of uq/master branch +of qemu-kvm.git repository + +maxcpus, which specifies the maximum number of hotpluggable CPUs, +should not exceed KVM's vcpu limit. + +Signed-off-by: Marcelo Tosatti +[Reword message. - Paolo] +Signed-off-by: Paolo Bonzini +BZ: 996258 + +Signed-off-by: Miroslav Rezanina +--- + kvm-all.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/kvm-all.c b/kvm-all.c +index 6c9d51e..545b470 100644 +--- a/kvm-all.c ++++ b/kvm-all.c +@@ -1358,6 +1358,13 @@ int kvm_init(void) + goto err; + } + ++ if (max_cpus > max_vcpus) { ++ ret = -EINVAL; ++ fprintf(stderr, "Number of hotpluggable cpus requested (%d) exceeds max cpus " ++ "supported by KVM (%d)\n", max_cpus, max_vcpus); ++ goto err; ++ } ++ + s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0); + if (s->vmfd < 0) { + #ifdef TARGET_S390X +-- +1.7.1 + diff --git a/SOURCES/kvm-apic-Document-why-cannot_instantiate_with_device_add.patch b/SOURCES/kvm-apic-Document-why-cannot_instantiate_with_device_add.patch new file mode 100644 index 0000000..79371c3 --- /dev/null +++ b/SOURCES/kvm-apic-Document-why-cannot_instantiate_with_device_add.patch @@ -0,0 +1,52 @@ +From 1bb88d69e0ad951f9436a79e5a5d4bb35bf4076d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:15 +0100 +Subject: [PATCH 39/81] apic: Document why cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-11-git-send-email-kwolf@redhat.com> +Patchwork-id: 55536 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 10/17] apic: Document why cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Peter Maydell +(cherry picked from pending upstream submission) +Signed-off-by: Kevin Wolf +--- + hw/intc/apic_common.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/intc/apic_common.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c +index 208e7b1..ff413de 100644 +--- a/hw/intc/apic_common.c ++++ b/hw/intc/apic_common.c +@@ -386,9 +386,13 @@ static void apic_common_class_init(ObjectClass *klass, void *data) + + dc->vmsd = &vmstate_apic_common; + dc->reset = apic_reset_common; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = apic_properties_common; + idc->init = apic_init_common; ++ /* ++ * Reason: APIC and CPU need to be wired up by ++ * x86_cpu_apic_create() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo apic_common_type = { +-- +1.7.1 + diff --git a/SOURCES/kvm-apic-rename-apic-specific-bitopts.patch b/SOURCES/kvm-apic-rename-apic-specific-bitopts.patch new file mode 100644 index 0000000..5d012c5 --- /dev/null +++ b/SOURCES/kvm-apic-rename-apic-specific-bitopts.patch @@ -0,0 +1,191 @@ +From 96d75583baef53a94ed53eec99f14951669f4155 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:06 +0100 +Subject: [PATCH 30/81] apic: rename apic specific bitopts + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 55527 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 01/17] apic: rename apic specific bitopts +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: "Michael S. Tsirkin" + +apic has its own version of bitops, with the +difference that it works on u32 and not long. +Add apic_ prefix to avoid namespace clashes. + +We should look into reusing standard bitops long-term, +but that's not entirely trivial. + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit edf9735e40841298874ee308fdecca2ac2aa5bdf) +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/intc/apic.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/intc/apic.c | 42 +++++++++++++++++++++--------------------- + 1 files changed, 21 insertions(+), 21 deletions(-) + +diff --git a/hw/intc/apic.c b/hw/intc/apic.c +index 756dff0..46cb097 100644 +--- a/hw/intc/apic.c ++++ b/hw/intc/apic.c +@@ -40,18 +40,18 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, + uint8_t dest, uint8_t dest_mode); + + /* Find first bit starting from msb */ +-static int fls_bit(uint32_t value) ++static int apic_fls_bit(uint32_t value) + { + return 31 - clz32(value); + } + + /* Find first bit starting from lsb */ +-static int ffs_bit(uint32_t value) ++static int apic_ffs_bit(uint32_t value) + { + return ctz32(value); + } + +-static inline void set_bit(uint32_t *tab, int index) ++static inline void apic_set_bit(uint32_t *tab, int index) + { + int i, mask; + i = index >> 5; +@@ -59,7 +59,7 @@ static inline void set_bit(uint32_t *tab, int index) + tab[i] |= mask; + } + +-static inline void reset_bit(uint32_t *tab, int index) ++static inline void apic_reset_bit(uint32_t *tab, int index) + { + int i, mask; + i = index >> 5; +@@ -67,7 +67,7 @@ static inline void reset_bit(uint32_t *tab, int index) + tab[i] &= ~mask; + } + +-static inline int get_bit(uint32_t *tab, int index) ++static inline int apic_get_bit(uint32_t *tab, int index) + { + int i, mask; + i = index >> 5; +@@ -81,7 +81,7 @@ static int get_highest_priority_int(uint32_t *tab) + int i; + for (i = 7; i >= 0; i--) { + if (tab[i] != 0) { +- return i * 32 + fls_bit(tab[i]); ++ return i * 32 + apic_fls_bit(tab[i]); + } + } + return -1; +@@ -184,7 +184,7 @@ void apic_deliver_pic_intr(DeviceState *d, int level) + case APIC_DM_FIXED: + if (!(lvt & APIC_LVT_LEVEL_TRIGGER)) + break; +- reset_bit(s->irr, lvt & 0xff); ++ apic_reset_bit(s->irr, lvt & 0xff); + /* fall through */ + case APIC_DM_EXTINT: + cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD); +@@ -230,7 +230,7 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, + d = -1; + for(i = 0; i < MAX_APIC_WORDS; i++) { + if (deliver_bitmask[i]) { +- d = i * 32 + ffs_bit(deliver_bitmask[i]); ++ d = i * 32 + apic_ffs_bit(deliver_bitmask[i]); + break; + } + } +@@ -386,13 +386,13 @@ void apic_poll_irq(DeviceState *d) + + static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode) + { +- apic_report_irq_delivered(!get_bit(s->irr, vector_num)); ++ apic_report_irq_delivered(!apic_get_bit(s->irr, vector_num)); + +- set_bit(s->irr, vector_num); ++ apic_set_bit(s->irr, vector_num); + if (trigger_mode) +- set_bit(s->tmr, vector_num); ++ apic_set_bit(s->tmr, vector_num); + else +- reset_bit(s->tmr, vector_num); ++ apic_reset_bit(s->tmr, vector_num); + if (s->vapic_paddr) { + apic_sync_vapic(s, SYNC_ISR_IRR_TO_VAPIC); + /* +@@ -412,8 +412,8 @@ static void apic_eoi(APICCommonState *s) + isrv = get_highest_priority_int(s->isr); + if (isrv < 0) + return; +- reset_bit(s->isr, isrv); +- if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) { ++ apic_reset_bit(s->isr, isrv); ++ if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && apic_get_bit(s->tmr, isrv)) { + ioapic_eoi_broadcast(isrv); + } + apic_sync_vapic(s, SYNC_FROM_VAPIC | SYNC_TO_VAPIC); +@@ -452,7 +452,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, + int idx = apic_find_dest(dest); + memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); + if (idx >= 0) +- set_bit(deliver_bitmask, idx); ++ apic_set_bit(deliver_bitmask, idx); + } + } else { + /* XXX: cluster mode */ +@@ -462,11 +462,11 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, + if (apic_iter) { + if (apic_iter->dest_mode == 0xf) { + if (dest & apic_iter->log_dest) +- set_bit(deliver_bitmask, i); ++ apic_set_bit(deliver_bitmask, i); + } else if (apic_iter->dest_mode == 0x0) { + if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && + (dest & apic_iter->log_dest & 0x0f)) { +- set_bit(deliver_bitmask, i); ++ apic_set_bit(deliver_bitmask, i); + } + } + } else { +@@ -509,14 +509,14 @@ static void apic_deliver(DeviceState *d, uint8_t dest, uint8_t dest_mode, + break; + case 1: + memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); +- set_bit(deliver_bitmask, s->idx); ++ apic_set_bit(deliver_bitmask, s->idx); + break; + case 2: + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); + break; + case 3: + memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); +- reset_bit(deliver_bitmask, s->idx); ++ apic_reset_bit(deliver_bitmask, s->idx); + break; + } + +@@ -573,8 +573,8 @@ int apic_get_interrupt(DeviceState *d) + apic_sync_vapic(s, SYNC_TO_VAPIC); + return s->spurious_vec & 0xff; + } +- reset_bit(s->irr, intno); +- set_bit(s->isr, intno); ++ apic_reset_bit(s->irr, intno); ++ apic_set_bit(s->isr, intno); + apic_sync_vapic(s, SYNC_TO_VAPIC); + + /* re-inject if there is still a pending PIC interrupt */ +-- +1.7.1 + diff --git a/SOURCES/kvm-audio-remove-CONFIG_MIXEMU-configure-option.patch b/SOURCES/kvm-audio-remove-CONFIG_MIXEMU-configure-option.patch new file mode 100644 index 0000000..1485073 --- /dev/null +++ b/SOURCES/kvm-audio-remove-CONFIG_MIXEMU-configure-option.patch @@ -0,0 +1,181 @@ +From 2254d0ce9d463c8a72ec9b1e21a9310231764c3a Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Tue, 15 Oct 2013 17:11:00 +0200 +Subject: [PATCH 23/25] audio: remove CONFIG_MIXEMU configure option + +RH-Author: Bandan Das +Message-id: <1381857067-9399-4-git-send-email-bsd@redhat.com> +Patchwork-id: 54951 +O-Subject: [PATCH RHEL-7 qemu-kvm v3 3/5] audio: remove CONFIG_MIXEMU configure option +Bugzilla: 954195 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster + +Signed-off-by: Bandan Das +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 19b0dfc19c0d911c322a03899806c59bc2f593c9) + +Conflicts: + configure +--- + audio/mixeng.c | 6 ------ + configure | 8 -------- + hw/audio/hda-codec.c | 30 ------------------------------ + 3 files changed, 44 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + audio/mixeng.c | 6 ------ + configure | 8 -------- + hw/audio/hda-codec.c | 30 ------------------------------ + 3 files changed, 0 insertions(+), 44 deletions(-) + +diff --git a/audio/mixeng.c b/audio/mixeng.c +index 02a9d9f..0e4976f 100644 +--- a/audio/mixeng.c ++++ b/audio/mixeng.c +@@ -348,7 +348,6 @@ void mixeng_clear (struct st_sample *buf, int len) + + void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol) + { +-#ifdef CONFIG_MIXEMU + if (vol->mute) { + mixeng_clear (buf, len); + return; +@@ -364,9 +363,4 @@ void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol) + #endif + buf += 1; + } +-#else +- (void) buf; +- (void) len; +- (void) vol; +-#endif + } +diff --git a/configure b/configure +index 02e483d..4d1bc44 100755 +--- a/configure ++++ b/configure +@@ -215,7 +215,6 @@ linux_user="no" + bsd_user="no" + guest_base="yes" + uname_release="" +-mixemu="no" + aix="no" + blobs="yes" + pkgversion="" +@@ -851,8 +850,6 @@ for opt do + ;; + --enable-nptl) nptl="yes" + ;; +- --enable-mixemu) mixemu="yes" +- ;; + --disable-linux-aio) linux_aio="no" + ;; + --enable-linux-aio) linux_aio="yes" +@@ -1115,7 +1112,6 @@ echo " (affects only QEMU, not qemu-img)" + echo " --block-drv-ro-whitelist=L" + echo " set block driver read-only whitelist" + echo " (affects only QEMU, not qemu-img)" +-echo " --enable-mixemu enable mixer emulation" + echo " --disable-xen disable xen backend driver support" + echo " --enable-xen enable xen backend driver support" + echo " --disable-xen-pci-passthrough" +@@ -3537,7 +3533,6 @@ echo "mingw32 support $mingw32" + echo "Audio drivers $audio_drv_list" + echo "Block whitelist (rw) $block_drv_rw_whitelist" + echo "Block whitelist (ro) $block_drv_ro_whitelist" +-echo "Mixer emulation $mixemu" + echo "VirtFS support $virtfs" + echo "VNC support $vnc" + if test "$vnc" = "yes" ; then +@@ -3719,9 +3714,6 @@ if test "$audio_win_int" = "yes" ; then + fi + echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak + echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak +-if test "$mixemu" = "yes" ; then +- echo "CONFIG_MIXEMU=y" >> $config_host_mak +-fi + if test "$vnc" = "yes" ; then + echo "CONFIG_VNC=y" >> $config_host_mak + fi +diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c +index 3217d90..94c472c 100644 +--- a/hw/audio/hda-codec.c ++++ b/hw/audio/hda-codec.c +@@ -118,11 +118,9 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as) + #define QEMU_HDA_AMP_NONE (0) + #define QEMU_HDA_AMP_STEPS 0x4a + +-#ifdef CONFIG_MIXEMU + #define PARAM mixemu + #define HDA_MIXER + #include "hda-codec-common.h" +-#endif + + #define PARAM nomixemu + #include "hda-codec-common.h" +@@ -594,11 +592,7 @@ static const VMStateDescription vmstate_hda_audio = { + + static Property hda_audio_properties[] = { + DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), +-#ifdef CONFIG_MIXEMU + DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true), +-#else +- DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, false), +-#endif + DEFINE_PROP_END_OF_LIST(), + }; + +@@ -609,15 +603,7 @@ static int hda_audio_init_output(HDACodecDevice *hda) + if (!a->mixer) { + return hda_audio_init(hda, &output_nomixemu); + } else { +- +-#ifdef CONFIG_MIXEMU + return hda_audio_init(hda, &output_mixemu); +-#else +- fprintf(stderr, "ERROR: " +- "hda-codec : Mixer emulation has not been compiled in!\n"); +- return -1; +-#endif +- + } + } + +@@ -628,15 +614,7 @@ static int hda_audio_init_duplex(HDACodecDevice *hda) + if (!a->mixer) { + return hda_audio_init(hda, &duplex_nomixemu); + } else { +- +-#ifdef CONFIG_MIXEMU + return hda_audio_init(hda, &duplex_mixemu); +-#else +- fprintf(stderr, "ERROR: " +- "hda-codec : Mixer emulation has not been compiled in!\n"); +- return -1; +-#endif +- + } + } + +@@ -647,15 +625,7 @@ static int hda_audio_init_micro(HDACodecDevice *hda) + if (!a->mixer) { + return hda_audio_init(hda, µ_nomixemu); + } else { +- +-#ifdef CONFIG_MIXEMU + return hda_audio_init(hda, µ_mixemu); +-#else +- fprintf(stderr, "ERROR: " +- "hda-codec : Mixer emulation has not been compiled in!\n"); +- return -1; +-#endif +- + } + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-bdrv-Use-Error-for-creating-images.patch b/SOURCES/kvm-bdrv-Use-Error-for-creating-images.patch new file mode 100644 index 0000000..1bb175a --- /dev/null +++ b/SOURCES/kvm-bdrv-Use-Error-for-creating-images.patch @@ -0,0 +1,321 @@ +From 3ba5256b9642a3313b9ffaf8abc0f6302e3e39e6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:10 +0100 +Subject: [PATCH 17/87] bdrv: Use "Error" for creating images + +RH-Author: Max Reitz +Message-id: <1383604354-12743-20-git-send-email-mreitz@redhat.com> +Patchwork-id: 55319 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 19/43] bdrv: Use "Error" for creating images +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Add an Error ** parameter to BlockDriver.bdrv_create to allow more +specific error messages. + +Signed-off-by: Max Reitz +(cherry picked from commit d5124c00d80b4d948509f2c7f6b54228d9981f75) + +Signed-off-by: Max Reitz + +Conflicts: + block/raw.c + block/raw_bsd.c + +Conflicts because raw_bsd.c does not exist downstream; instead, there is +raw.c. +--- + block.c | 2 +- + block/cow.c | 3 ++- + block/gluster.c | 2 +- + block/iscsi.c | 3 ++- + block/qcow.c | 3 ++- + block/qcow2.c | 3 ++- + block/qed.c | 3 ++- + block/raw-posix.c | 6 ++++-- + block/raw-win32.c | 3 ++- + block/raw.c | 3 ++- + block/rbd.c | 3 ++- + block/sheepdog.c | 3 ++- + block/ssh.c | 3 ++- + block/vdi.c | 3 ++- + block/vmdk.c | 3 ++- + block/vpc.c | 3 ++- + include/block/block_int.h | 3 ++- + 17 files changed, 34 insertions(+), 18 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 2 +- + block/cow.c | 3 ++- + block/gluster.c | 2 +- + block/iscsi.c | 3 ++- + block/qcow.c | 3 ++- + block/qcow2.c | 3 ++- + block/qed.c | 3 ++- + block/raw-posix.c | 6 ++++-- + block/raw-win32.c | 3 ++- + block/raw.c | 3 ++- + block/rbd.c | 3 ++- + block/sheepdog.c | 3 ++- + block/ssh.c | 3 ++- + block/vdi.c | 3 ++- + block/vmdk.c | 3 ++- + block/vpc.c | 3 ++- + include/block/block_int.h | 3 ++- + 17 files changed, 34 insertions(+), 18 deletions(-) + +diff --git a/block.c b/block.c +index 921fa33..0cb5ac9 100644 +--- a/block.c ++++ b/block.c +@@ -373,7 +373,7 @@ static void coroutine_fn bdrv_create_co_entry(void *opaque) + CreateCo *cco = opaque; + assert(cco->drv); + +- cco->ret = cco->drv->bdrv_create(cco->filename, cco->options); ++ cco->ret = cco->drv->bdrv_create(cco->filename, cco->options, NULL); + } + + int bdrv_create(BlockDriver *drv, const char* filename, +diff --git a/block/cow.c b/block/cow.c +index ce8deb8..c1d2dc8 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -295,7 +295,8 @@ static void cow_close(BlockDriverState *bs) + { + } + +-static int cow_create(const char *filename, QEMUOptionParameter *options) ++static int cow_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + struct cow_header_v2 cow_header; + struct stat st; +diff --git a/block/gluster.c b/block/gluster.c +index fa46b6f..bf39264 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -366,7 +366,7 @@ out: + } + + static int qemu_gluster_create(const char *filename, +- QEMUOptionParameter *options) ++ QEMUOptionParameter *options, Error **errp) + { + struct glfs *glfs; + struct glfs_fd *fd; +diff --git a/block/iscsi.c b/block/iscsi.c +index 8d49e35..ac35caa 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1249,7 +1249,8 @@ static int iscsi_has_zero_init(BlockDriverState *bs) + return 0; + } + +-static int iscsi_create(const char *filename, QEMUOptionParameter *options) ++static int iscsi_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int ret = 0; + int64_t total_size = 0; +diff --git a/block/qcow.c b/block/qcow.c +index b8887f0..1a6926f 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -659,7 +659,8 @@ static void qcow_close(BlockDriverState *bs) + error_free(s->migration_blocker); + } + +-static int qcow_create(const char *filename, QEMUOptionParameter *options) ++static int qcow_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int header_size, backing_filename_len, l1_size, shift, i; + QCowHeader header; +diff --git a/block/qcow2.c b/block/qcow2.c +index 2e7e9f5..b6e50af 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1467,7 +1467,8 @@ out: + return ret; + } + +-static int qcow2_create(const char *filename, QEMUOptionParameter *options) ++static int qcow2_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + const char *backing_file = NULL; + const char *backing_fmt = NULL; +diff --git a/block/qed.c b/block/qed.c +index d49e0cd..c56b5e2 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -604,7 +604,8 @@ out: + return ret; + } + +-static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options) ++static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + uint64_t image_size = 0; + uint32_t cluster_size = QED_DEFAULT_CLUSTER_SIZE; +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 5f4e824..249bffb 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -1041,7 +1041,8 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs) + return (int64_t)st.st_blocks * 512; + } + +-static int raw_create(const char *filename, QEMUOptionParameter *options) ++static int raw_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int fd; + int result = 0; +@@ -1505,7 +1506,8 @@ static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs, + cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV); + } + +-static int hdev_create(const char *filename, QEMUOptionParameter *options) ++static int hdev_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int fd; + int ret = 0; +diff --git a/block/raw-win32.c b/block/raw-win32.c +index 1cfec65..9ebb083 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -421,7 +421,8 @@ static int64_t raw_get_allocated_file_size(BlockDriverState *bs) + return st.st_size; + } + +-static int raw_create(const char *filename, QEMUOptionParameter *options) ++static int raw_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int fd; + int64_t total_size = 0; +diff --git a/block/raw.c b/block/raw.c +index 801591d..f92c04e 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -105,7 +105,8 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, + return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque); + } + +-static int raw_create(const char *filename, QEMUOptionParameter *options) ++static int raw_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + return bdrv_create_file(filename, options); + } +diff --git a/block/rbd.c b/block/rbd.c +index 8d4ae9f..169d3cf 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -286,7 +286,8 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf) + return ret; + } + +-static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) ++static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int64_t bytes = 0; + int64_t objsize; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index a8ce933..952d703 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1455,7 +1455,8 @@ out: + return ret; + } + +-static int sd_create(const char *filename, QEMUOptionParameter *options) ++static int sd_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int ret = 0; + uint32_t vid = 0, base_vid = 0; +diff --git a/block/ssh.c b/block/ssh.c +index f950fcc..fa3c78d 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -651,7 +651,8 @@ static QEMUOptionParameter ssh_create_options[] = { + { NULL } + }; + +-static int ssh_create(const char *filename, QEMUOptionParameter *options) ++static int ssh_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int r, ret; + Error *local_err = NULL; +diff --git a/block/vdi.c b/block/vdi.c +index 661c3f0..84860fe 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -645,7 +645,8 @@ static int vdi_co_write(BlockDriverState *bs, + return ret; + } + +-static int vdi_create(const char *filename, QEMUOptionParameter *options) ++static int vdi_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int fd; + int result = 0; +diff --git a/block/vmdk.c b/block/vmdk.c +index d9e2545..fa64f05 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1552,7 +1552,8 @@ static int filename_decompose(const char *filename, char *path, char *prefix, + return VMDK_OK; + } + +-static int vmdk_create(const char *filename, QEMUOptionParameter *options) ++static int vmdk_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + int fd, idx = 0; + char desc[BUF_SIZE]; +diff --git a/block/vpc.c b/block/vpc.c +index cf5e751..5d65756 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -684,7 +684,8 @@ static int create_fixed_disk(int fd, uint8_t *buf, int64_t total_size) + return ret; + } + +-static int vpc_create(const char *filename, QEMUOptionParameter *options) ++static int vpc_create(const char *filename, QEMUOptionParameter *options, ++ Error **errp) + { + uint8_t buf[1024]; + struct vhd_footer *footer = (struct vhd_footer *) buf; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 3450b46..696bbb9 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -96,7 +96,8 @@ struct BlockDriver { + const uint8_t *buf, int nb_sectors); + void (*bdrv_close)(BlockDriverState *bs); + void (*bdrv_rebind)(BlockDriverState *bs); +- int (*bdrv_create)(const char *filename, QEMUOptionParameter *options); ++ int (*bdrv_create)(const char *filename, QEMUOptionParameter *options, ++ Error **errp); + int (*bdrv_set_key)(BlockDriverState *bs, const char *key); + int (*bdrv_make_empty)(BlockDriverState *bs); + /* aio */ +-- +1.7.1 + diff --git a/SOURCES/kvm-bdrv-Use-Error-for-opening-images.patch b/SOURCES/kvm-bdrv-Use-Error-for-opening-images.patch new file mode 100644 index 0000000..aeef381 --- /dev/null +++ b/SOURCES/kvm-bdrv-Use-Error-for-opening-images.patch @@ -0,0 +1,565 @@ +From cbf4a883b38edbd2740c0ed374e1101fe56513bf Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:09 +0100 +Subject: [PATCH 16/87] bdrv: Use "Error" for opening images + +RH-Author: Max Reitz +Message-id: <1383604354-12743-19-git-send-email-mreitz@redhat.com> +Patchwork-id: 55318 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 18/43] bdrv: Use "Error" for opening images +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Add an Error ** parameter to BlockDriver.bdrv_open and +BlockDriver.bdrv_file_open to allow more specific error messages. + +Signed-off-by: Max Reitz +(cherry picked from commit 015a1036a74ad29bb6916754911ce25587ff4db3) + +Signed-off-by: Max Reitz + +Conflicts: + block/raw.c + block/raw_bsd.c + +Conflicts because raw_bsd.c does not exist downstream; instead, there is +raw.c. +--- + block.c | 4 ++-- + block/blkdebug.c | 3 ++- + block/blkverify.c | 3 ++- + block/bochs.c | 3 ++- + block/cloop.c | 3 ++- + block/cow.c | 3 ++- + block/curl.c | 3 ++- + block/dmg.c | 3 ++- + block/gluster.c | 2 +- + block/iscsi.c | 5 +++-- + block/nbd.c | 3 ++- + block/parallels.c | 3 ++- + block/qcow.c | 3 ++- + block/qcow2.c | 5 +++-- + block/qed.c | 5 +++-- + block/raw-posix.c | 12 ++++++++---- + block/raw-win32.c | 6 ++++-- + block/raw.c | 3 ++- + block/rbd.c | 3 ++- + block/sheepdog.c | 3 ++- + block/snapshot.c | 2 +- + block/ssh.c | 3 ++- + block/vdi.c | 3 ++- + block/vhdx.c | 3 ++- + block/vmdk.c | 3 ++- + block/vpc.c | 3 ++- + block/vvfat.c | 3 ++- + include/block/block_int.h | 6 ++++-- + 28 files changed, 67 insertions(+), 37 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 4 ++-- + block/blkdebug.c | 3 ++- + block/blkverify.c | 3 ++- + block/bochs.c | 3 ++- + block/cloop.c | 3 ++- + block/cow.c | 3 ++- + block/curl.c | 3 ++- + block/dmg.c | 3 ++- + block/gluster.c | 2 +- + block/iscsi.c | 5 +++-- + block/nbd.c | 3 ++- + block/parallels.c | 3 ++- + block/qcow.c | 3 ++- + block/qcow2.c | 5 +++-- + block/qed.c | 5 +++-- + block/raw-posix.c | 12 ++++++++---- + block/raw-win32.c | 6 ++++-- + block/raw.c | 3 ++- + block/rbd.c | 3 ++- + block/sheepdog.c | 3 ++- + block/snapshot.c | 2 +- + block/ssh.c | 3 ++- + block/vdi.c | 3 ++- + block/vhdx.c | 3 ++- + block/vmdk.c | 3 ++- + block/vpc.c | 3 ++- + block/vvfat.c | 3 ++- + include/block/block_int.h | 6 ++++-- + 28 files changed, 67 insertions(+), 37 deletions(-) + +diff --git a/block.c b/block.c +index 69b70d0..921fa33 100644 +--- a/block.c ++++ b/block.c +@@ -733,7 +733,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + if (drv->bdrv_file_open) { + assert(file == NULL); + assert(drv->bdrv_parse_filename || filename != NULL); +- ret = drv->bdrv_file_open(bs, options, open_flags); ++ ret = drv->bdrv_file_open(bs, options, open_flags, NULL); + } else { + if (file == NULL) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't use '%s' as a " +@@ -744,7 +744,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + } + assert(file != NULL); + bs->file = file; +- ret = drv->bdrv_open(bs, options, open_flags); ++ ret = drv->bdrv_open(bs, options, open_flags, NULL); + } + + if (ret < 0) { +diff --git a/block/blkdebug.c b/block/blkdebug.c +index d659d38..114c4c9 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -347,7 +347,8 @@ static QemuOptsList runtime_opts = { + }, + }; + +-static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags) ++static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVBlkdebugState *s = bs->opaque; + QemuOpts *opts; +diff --git a/block/blkverify.c b/block/blkverify.c +index 1d58cc3..5d716bb 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -116,7 +116,8 @@ static QemuOptsList runtime_opts = { + }, + }; + +-static int blkverify_open(BlockDriverState *bs, QDict *options, int flags) ++static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVBlkverifyState *s = bs->opaque; + QemuOpts *opts; +diff --git a/block/bochs.c b/block/bochs.c +index d7078c0..51d9a90 100644 +--- a/block/bochs.c ++++ b/block/bochs.c +@@ -108,7 +108,8 @@ static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename) + return 0; + } + +-static int bochs_open(BlockDriverState *bs, QDict *options, int flags) ++static int bochs_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVBochsState *s = bs->opaque; + int i; +diff --git a/block/cloop.c b/block/cloop.c +index 6ea7cf4..b907023 100644 +--- a/block/cloop.c ++++ b/block/cloop.c +@@ -53,7 +53,8 @@ static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) + return 0; + } + +-static int cloop_open(BlockDriverState *bs, QDict *options, int flags) ++static int cloop_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVCloopState *s = bs->opaque; + uint32_t offsets_size, max_compressed_block_size = 1, i; +diff --git a/block/cow.c b/block/cow.c +index 6958808..ce8deb8 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -58,7 +58,8 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename) + return 0; + } + +-static int cow_open(BlockDriverState *bs, QDict *options, int flags) ++static int cow_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVCowState *s = bs->opaque; + struct cow_header_v2 cow_header; +diff --git a/block/curl.c b/block/curl.c +index b8935fd..1b0fcf1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -395,7 +395,8 @@ static QemuOptsList runtime_opts = { + }, + }; + +-static int curl_open(BlockDriverState *bs, QDict *options, int flags) ++static int curl_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVCURLState *s = bs->opaque; + CURLState *state = NULL; +diff --git a/block/dmg.c b/block/dmg.c +index 3141cb5..d5e9b1f 100644 +--- a/block/dmg.c ++++ b/block/dmg.c +@@ -92,7 +92,8 @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result) + return 0; + } + +-static int dmg_open(BlockDriverState *bs, QDict *options, int flags) ++static int dmg_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVDMGState *s = bs->opaque; + uint64_t info_begin,info_end,last_in_offset,last_out_offset; +diff --git a/block/gluster.c b/block/gluster.c +index 90a51ca..fa46b6f 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -297,7 +297,7 @@ static QemuOptsList runtime_opts = { + }; + + static int qemu_gluster_open(BlockDriverState *bs, QDict *options, +- int bdrv_flags) ++ int bdrv_flags, Error **errp) + { + BDRVGlusterState *s = bs->opaque; + int open_flags = O_BINARY; +diff --git a/block/iscsi.c b/block/iscsi.c +index cc2017e..8d49e35 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1056,7 +1056,8 @@ static QemuOptsList runtime_opts = { + * We support iscsi url's on the form + * iscsi://[%@][:]// + */ +-static int iscsi_open(BlockDriverState *bs, QDict *options, int flags) ++static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + IscsiLun *iscsilun = bs->opaque; + struct iscsi_context *iscsi = NULL; +@@ -1271,7 +1272,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) + + bs_options = qdict_new(); + qdict_put(bs_options, "filename", qstring_from_str(filename)); +- ret = iscsi_open(bs, bs_options, 0); ++ ret = iscsi_open(bs, bs_options, 0, NULL); + QDECREF(bs_options); + + if (ret != 0) { +diff --git a/block/nbd.c b/block/nbd.c +index 9c480b8..48a759e 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -463,7 +463,8 @@ static void nbd_teardown_connection(BlockDriverState *bs) + closesocket(s->sock); + } + +-static int nbd_open(BlockDriverState *bs, QDict *options, int flags) ++static int nbd_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVNBDState *s = bs->opaque; + int result; +diff --git a/block/parallels.c b/block/parallels.c +index 18b3ac0..2121e43 100644 +--- a/block/parallels.c ++++ b/block/parallels.c +@@ -68,7 +68,8 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam + return 0; + } + +-static int parallels_open(BlockDriverState *bs, QDict *options, int flags) ++static int parallels_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVParallelsState *s = bs->opaque; + int i; +diff --git a/block/qcow.c b/block/qcow.c +index 4ab552e..b8887f0 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -92,7 +92,8 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) + return 0; + } + +-static int qcow_open(BlockDriverState *bs, QDict *options, int flags) ++static int qcow_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVQcowState *s = bs->opaque; + int len, i, shift, ret; +diff --git a/block/qcow2.c b/block/qcow2.c +index 8a30863..2e7e9f5 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -350,7 +350,8 @@ static QemuOptsList qcow2_runtime_opts = { + }, + }; + +-static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) ++static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVQcowState *s = bs->opaque; + int len, i, ret = 0; +@@ -1059,7 +1060,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs) + qbool_from_int(s->use_lazy_refcounts)); + + memset(s, 0, sizeof(BDRVQcowState)); +- qcow2_open(bs, options, flags); ++ qcow2_open(bs, options, flags, NULL); + + QDECREF(options); + +diff --git a/block/qed.c b/block/qed.c +index 815ee1c..d49e0cd 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -373,7 +373,8 @@ static void bdrv_qed_rebind(BlockDriverState *bs) + s->bs = bs; + } + +-static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags) ++static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVQEDState *s = bs->opaque; + QEDHeader le_header; +@@ -1547,7 +1548,7 @@ static void bdrv_qed_invalidate_cache(BlockDriverState *bs) + + bdrv_qed_close(bs); + memset(s, 0, sizeof(BDRVQEDState)); +- bdrv_qed_open(bs, NULL, bs->open_flags); ++ bdrv_qed_open(bs, NULL, bs->open_flags, NULL); + } + + static int bdrv_qed_check(BlockDriverState *bs, BdrvCheckResult *result, +diff --git a/block/raw-posix.c b/block/raw-posix.c +index c7ab908..5f4e824 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -335,7 +335,8 @@ fail: + return ret; + } + +-static int raw_open(BlockDriverState *bs, QDict *options, int flags) ++static int raw_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + +@@ -1330,7 +1331,8 @@ static int check_hdev_writable(BDRVRawState *s) + return 0; + } + +-static int hdev_open(BlockDriverState *bs, QDict *options, int flags) ++static int hdev_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + int ret; +@@ -1570,7 +1572,8 @@ static BlockDriver bdrv_host_device = { + }; + + #ifdef __linux__ +-static int floppy_open(BlockDriverState *bs, QDict *options, int flags) ++static int floppy_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + int ret; +@@ -1692,7 +1695,8 @@ static BlockDriver bdrv_host_floppy = { + .bdrv_eject = floppy_eject, + }; + +-static int cdrom_open(BlockDriverState *bs, QDict *options, int flags) ++static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + +diff --git a/block/raw-win32.c b/block/raw-win32.c +index a324e5b..1cfec65 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -234,7 +234,8 @@ static QemuOptsList raw_runtime_opts = { + }, + }; + +-static int raw_open(BlockDriverState *bs, QDict *options, int flags) ++static int raw_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + int access_flags; +@@ -530,7 +531,8 @@ static int hdev_probe_device(const char *filename) + return 0; + } + +-static int hdev_open(BlockDriverState *bs, QDict *options, int flags) ++static int hdev_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRawState *s = bs->opaque; + int access_flags, create_flags; +diff --git a/block/raw.c b/block/raw.c +index 7d82cf3..801591d 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -3,7 +3,8 @@ + #include "block/block_int.h" + #include "qemu/module.h" + +-static int raw_open(BlockDriverState *bs, QDict *options, int flags) ++static int raw_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + bs->sg = bs->file->sg; + return 0; +diff --git a/block/rbd.c b/block/rbd.c +index 7b6e03b..8d4ae9f 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -457,7 +457,8 @@ static QemuOptsList runtime_opts = { + }, + }; + +-static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags) ++static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVRBDState *s = bs->opaque; + char pool[RBD_MAX_POOL_NAME_SIZE]; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index f7cc76e..a8ce933 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1259,7 +1259,8 @@ static QemuOptsList runtime_opts = { + }, + }; + +-static int sd_open(BlockDriverState *bs, QDict *options, int flags) ++static int sd_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + int ret, fd; + uint32_t vid = 0; +diff --git a/block/snapshot.c b/block/snapshot.c +index 6c6d9de..51b4b96 100644 +--- a/block/snapshot.c ++++ b/block/snapshot.c +@@ -97,7 +97,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs, + if (bs->file) { + drv->bdrv_close(bs); + ret = bdrv_snapshot_goto(bs->file, snapshot_id); +- open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); ++ open_ret = drv->bdrv_open(bs, NULL, bs->open_flags, NULL); + if (open_ret < 0) { + bdrv_delete(bs->file); + bs->drv = NULL; +diff --git a/block/ssh.c b/block/ssh.c +index d7e7bf8..f950fcc 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -608,7 +608,8 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options, + return ret; + } + +-static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags) ++static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, ++ Error **errp) + { + BDRVSSHState *s = bs->opaque; + int ret; +diff --git a/block/vdi.c b/block/vdi.c +index bc97c39..661c3f0 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -364,7 +364,8 @@ static int vdi_probe(const uint8_t *buf, int buf_size, const char *filename) + return result; + } + +-static int vdi_open(BlockDriverState *bs, QDict *options, int flags) ++static int vdi_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVVdiState *s = bs->opaque; + VdiHeader header; +diff --git a/block/vhdx.c b/block/vhdx.c +index 11d923f..6cb0412 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -717,7 +717,8 @@ exit: + } + + +-static int vhdx_open(BlockDriverState *bs, QDict *options, int flags) ++static int vhdx_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVVHDXState *s = bs->opaque; + int ret = 0; +diff --git a/block/vmdk.c b/block/vmdk.c +index 7456f9b..d9e2545 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -806,7 +806,8 @@ exit: + return ret; + } + +-static int vmdk_open(BlockDriverState *bs, QDict *options, int flags) ++static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + int ret; + BDRVVmdkState *s = bs->opaque; +diff --git a/block/vpc.c b/block/vpc.c +index 3cad52e..cf5e751 100644 +--- a/block/vpc.c ++++ b/block/vpc.c +@@ -155,7 +155,8 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename) + return 0; + } + +-static int vpc_open(BlockDriverState *bs, QDict *options, int flags) ++static int vpc_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVVPCState *s = bs->opaque; + int i; +diff --git a/block/vvfat.c b/block/vvfat.c +index dd0efca..bb3b0b6 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -1065,7 +1065,8 @@ static void vvfat_parse_filename(const char *filename, QDict *options, + qdict_put(options, "rw", qbool_from_int(rw)); + } + +-static int vvfat_open(BlockDriverState *bs, QDict *options, int flags) ++static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp) + { + BDRVVVFATState *s = bs->opaque; + int cyls, heads, secs; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index ea2c811..3450b46 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -86,8 +86,10 @@ struct BlockDriver { + void (*bdrv_reopen_commit)(BDRVReopenState *reopen_state); + void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state); + +- int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags); +- int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags); ++ int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp); ++ int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags, ++ Error **errp); + int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors); + int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, +-- +1.7.1 + diff --git a/SOURCES/kvm-blkdebug-Employ-error-parameter.patch b/SOURCES/kvm-blkdebug-Employ-error-parameter.patch new file mode 100644 index 0000000..6dd766f --- /dev/null +++ b/SOURCES/kvm-blkdebug-Employ-error-parameter.patch @@ -0,0 +1,75 @@ +From ce32a49212b68b1325144c61b9d1e0acebdc286c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:18 +0100 +Subject: [PATCH 25/87] blkdebug: Employ error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-28-git-send-email-mreitz@redhat.com> +Patchwork-id: 55327 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 27/43] blkdebug: Employ error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Make use of the error parameter in blkdebug_open. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 10ffa72faed7e02805d7911d58d429efe6f95f93) + +Signed-off-by: Max Reitz +--- + block/blkdebug.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/blkdebug.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/block/blkdebug.c b/block/blkdebug.c +index eda2810..9ee4fbb 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -359,8 +359,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + opts = qemu_opts_create_nofail(&runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -370,6 +369,7 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + if (config) { + ret = read_config(s, config); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read blkdebug config file"); + goto fail; + } + } +@@ -380,14 +380,14 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + /* Open the backing file */ + filename = qemu_opt_get(opts, "x-image"); + if (filename == NULL) { ++ error_setg(errp, "Could not retrieve image file name"); + ret = -EINVAL; + goto fail; + } + + ret = bdrv_file_open(&bs->file, filename, NULL, flags, &local_err); + if (ret < 0) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + goto fail; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-blkverify-Employ-error-parameter.patch b/SOURCES/kvm-blkverify-Employ-error-parameter.patch new file mode 100644 index 0000000..d2f303c --- /dev/null +++ b/SOURCES/kvm-blkverify-Employ-error-parameter.patch @@ -0,0 +1,90 @@ +From 933ac03653bd2ec6194811b5c73b871854382298 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:19 +0100 +Subject: [PATCH 26/87] blkverify: Employ error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-29-git-send-email-mreitz@redhat.com> +Patchwork-id: 55328 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 28/43] blkverify: Employ error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Make use of the error parameter in blkverify_open. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit ca2884087a36c60d592aa0e8e327bf1579972077) + +Signed-off-by: Max Reitz + +Conflicts: + block/blkverify.c + +Conflicts because "Implement reference count for BlockDriverState" has +not yet been backported. +--- + block/blkverify.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/blkverify.c | 11 +++++------ + 1 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/block/blkverify.c b/block/blkverify.c +index cceb88f..92a452d 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -128,8 +128,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + opts = qemu_opts_create_nofail(&runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -137,20 +136,21 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + /* Parse the raw image filename */ + raw = qemu_opt_get(opts, "x-raw"); + if (raw == NULL) { ++ error_setg(errp, "Could not retrieve raw image filename"); + ret = -EINVAL; + goto fail; + } + + ret = bdrv_file_open(&bs->file, raw, NULL, flags, &local_err); + if (ret < 0) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + goto fail; + } + + /* Open the test file */ + filename = qemu_opt_get(opts, "x-image"); + if (filename == NULL) { ++ error_setg(errp, "Could not retrieve test image filename"); + ret = -EINVAL; + goto fail; + } +@@ -158,8 +158,7 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + s->test_file = bdrv_new(""); + ret = bdrv_open(s->test_file, filename, NULL, flags, NULL, &local_err); + if (ret < 0) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + bdrv_delete(s->test_file); + s->test_file = NULL; + goto fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Add-bdrv_get_specific_info.patch b/SOURCES/kvm-block-Add-bdrv_get_specific_info.patch new file mode 100644 index 0000000..9a3f68b --- /dev/null +++ b/SOURCES/kvm-block-Add-bdrv_get_specific_info.patch @@ -0,0 +1,101 @@ +From c6de1e3f478b5449d1283c66164c5ede351db600 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:35 +0100 +Subject: [PATCH 78/87] block: Add bdrv_get_specific_info + +RH-Author: Max Reitz +Message-id: <1383756824-6921-13-git-send-email-mreitz@redhat.com> +Patchwork-id: 55567 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 12/21] block: Add bdrv_get_specific_info +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +Add a function for retrieving an ImageInfoSpecific object from a block +driver. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit eae041fe6f4314962e873615134eefb32cf8ba61) + +Signed-off-by: Max Reitz +--- + block.c | 9 +++++++++ + block/qapi.c | 3 +++ + include/block/block.h | 1 + + include/block/block_int.h | 1 + + 4 files changed, 14 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 9 +++++++++ + block/qapi.c | 3 +++ + include/block/block.h | 1 + + include/block/block_int.h | 1 + + 4 files changed, 14 insertions(+), 0 deletions(-) + +diff --git a/block.c b/block.c +index e4885da..6913799 100644 +--- a/block.c ++++ b/block.c +@@ -3309,6 +3309,15 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) + return drv->bdrv_get_info(bs, bdi); + } + ++ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs) ++{ ++ BlockDriver *drv = bs->drv; ++ if (drv && drv->bdrv_get_specific_info) { ++ return drv->bdrv_get_specific_info(bs); ++ } ++ return NULL; ++} ++ + int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf, + int64_t pos, int size) + { +diff --git a/block/qapi.c b/block/qapi.c +index a4bc411..896cd37 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -134,6 +134,9 @@ void bdrv_query_image_info(BlockDriverState *bs, + info->dirty_flag = bdi.is_dirty; + info->has_dirty_flag = true; + } ++ info->format_specific = bdrv_get_specific_info(bs); ++ info->has_format_specific = info->format_specific != NULL; ++ + backing_filename = bs->backing_file; + if (backing_filename[0] != '\0') { + info->backing_filename = g_strdup(backing_filename); +diff --git a/include/block/block.h b/include/block/block.h +index 7695cae..656570e 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -338,6 +338,7 @@ int bdrv_get_flags(BlockDriverState *bs); + int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); + int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi); ++ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs); + void bdrv_round_to_clusters(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, + int64_t *cluster_sector_num, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 9348238..0dbc34f 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -166,6 +166,7 @@ struct BlockDriver { + int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs, + const char *snapshot_name); + int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi); ++ ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs); + + int (*bdrv_save_vmstate)(BlockDriverState *bs, QEMUIOVector *qiov, + int64_t pos); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Allow-driver-option-on-the-top-level.patch b/SOURCES/kvm-block-Allow-driver-option-on-the-top-level.patch new file mode 100644 index 0000000..e2f591e --- /dev/null +++ b/SOURCES/kvm-block-Allow-driver-option-on-the-top-level.patch @@ -0,0 +1,141 @@ +From c9489944db197e5c1b4086dc92a41f6c364976b0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:17 +0200 +Subject: [PATCH 26/38] block: Allow "driver" option on the top level + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-27-git-send-email-kwolf@redhat.com> +Patchwork-id: 54213 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 26/32] block: Allow "driver" option on the top level +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This is traditionally -drive format=..., which is now translated into +the new driver option. This gives us a more consistent way to select the +driver of BlockDriverStates that can be used in QMP context, too. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 74fe54f2a1b5c4f4498a8fe521e1dfc936656cd4) + +Signed-off-by: Kevin Wolf +--- + block.c | 7 +++++++ + blockdev.c | 20 ++++++++++---------- + 2 files changed, 17 insertions(+), 10 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 7 +++++++ + blockdev.c | 20 ++++++++++---------- + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/block.c b/block.c +index 20820fa..f4a89b9 100644 +--- a/block.c ++++ b/block.c +@@ -972,6 +972,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + char tmp_filename[PATH_MAX + 1]; + BlockDriverState *file = NULL; + QDict *file_options = NULL; ++ const char *drvname; + + /* NULL means an empty set of options */ + if (options == NULL) { +@@ -1061,6 +1062,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + } + + /* Find the right image format driver */ ++ drvname = qdict_get_try_str(options, "driver"); ++ if (drvname) { ++ drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); ++ qdict_del(options, "driver"); ++ } ++ + if (!drv) { + ret = find_image_format(file, filename, &drv); + } +diff --git a/blockdev.c b/blockdev.c +index bd33c17..1c9ca4d 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -322,7 +322,6 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + enum { MEDIA_DISK, MEDIA_CDROM } media; + int bus_id, unit_id; + int cyls, heads, secs, translation; +- BlockDriver *drv = NULL; + int max_devs; + int index; + int ro = 0; +@@ -338,6 +337,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + QemuOpts *opts; + QDict *bs_opts; + const char *id; ++ bool has_driver_specific_opts; + + translation = BIOS_ATA_TRANSLATION_AUTO; + media = MEDIA_DISK; +@@ -365,6 +365,8 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + qdict_del(bs_opts, "id"); + } + ++ has_driver_specific_opts = !!qdict_size(bs_opts); ++ + /* extract parameters */ + bus_id = qemu_opt_get_number(opts, "bus", 0); + unit_id = qemu_opt_get_number(opts, "unit", -1); +@@ -477,11 +479,8 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + error_printf("\n"); + return NULL; + } +- drv = bdrv_find_whitelisted_format(buf, ro); +- if (!drv) { +- error_report("'%s' invalid format", buf); +- return NULL; +- } ++ ++ qdict_put(bs_opts, "driver", qstring_from_str(buf)); + } + + /* disk I/O throttling */ +@@ -658,7 +657,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + abort(); + } + if (!file || !*file) { +- if (qdict_size(bs_opts)) { ++ if (has_driver_specific_opts) { + file = NULL; + } else { + return dinfo; +@@ -695,13 +694,13 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + error_report("warning: disabling copy_on_read on readonly drive"); + } + +- ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv); +- bs_opts = NULL; ++ QINCREF(bs_opts); ++ ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, NULL); + + if (ret < 0) { + if (ret == -EMEDIUMTYPE) { + error_report("could not open disk image %s: not in %s format", +- file ?: dinfo->id, drv->format_name); ++ file ?: dinfo->id, qdict_get_str(bs_opts, "driver")); + } else { + error_report("could not open disk image %s: %s", + file ?: dinfo->id, strerror(-ret)); +@@ -712,6 +711,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + if (bdrv_key_required(dinfo->bdrv)) + autostart = 0; + ++ QDECREF(bs_opts); + qemu_opts_del(opts); + + return dinfo; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Always-enable-discard-on-the-protocol-level.patch b/SOURCES/kvm-block-Always-enable-discard-on-the-protocol-level.patch new file mode 100644 index 0000000..3848270 --- /dev/null +++ b/SOURCES/kvm-block-Always-enable-discard-on-the-protocol-level.patch @@ -0,0 +1,58 @@ +From c1a149658ffb385f55e8bb06f06b6d195b91fd1b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:03 +0200 +Subject: [PATCH 12/38] block: Always enable discard on the protocol level + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-13-git-send-email-kwolf@redhat.com> +Patchwork-id: 54196 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 12/32] block: Always enable discard on the protocol level +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Turning on discard options in qcow2 doesn't help a lot when the discard +requests that it issues are thrown away by the raw-posix layer. This +patch always enables discard functionality on the protocol level so that +it's the image format's responsibility to send (or not) discard +requests. Requests sent by the guest will be allowed or ignored by the +top level BlockDriverState, which depends on the discard=... option like +before. + +In particular, this means that even without specifying options, the +qcow2 default of discarding deleted snapshots actually takes effect now, +both for qemu and qemu-img. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 50b05b6f2e24296b4d739a638e1e7427767ed7cd) + +Signed-off-by: Kevin Wolf +--- + block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 2584ec7..20820fa 100644 +--- a/block.c ++++ b/block.c +@@ -1055,7 +1055,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + extract_subqdict(options, &file_options, "file."); + + ret = bdrv_file_open(&file, filename, file_options, +- bdrv_open_flags(bs, flags)); ++ bdrv_open_flags(bs, flags | BDRV_O_UNMAP)); + if (ret < 0) { + goto fail; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Bugfix-format-and-snapshot-used-in-drive-optio.patch b/SOURCES/kvm-block-Bugfix-format-and-snapshot-used-in-drive-optio.patch new file mode 100644 index 0000000..68720fb --- /dev/null +++ b/SOURCES/kvm-block-Bugfix-format-and-snapshot-used-in-drive-optio.patch @@ -0,0 +1,89 @@ +From 3cae2bf94bf3ef300facbd31214dbeae7b2ad7b7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:57 +0100 +Subject: [PATCH 04/87] block: Bugfix 'format' and 'snapshot' used in drive option + +RH-Author: Max Reitz +Message-id: <1383604354-12743-7-git-send-email-mreitz@redhat.com> +Patchwork-id: 55306 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 06/43] block: Bugfix 'format' and 'snapshot' used in drive option +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Mike Qiu + +BZ: 1026524 + +When use -drive file='xxx',format=qcow2,snapshot=on the error +message "Can't use snapshot=on with driver-specific options" +can be show, and fail to start the qemu. + +This should not be happened, and there is no file.driver option +in qemu command line. + +It is because the commit 74fe54f2a1b5c4f4498a8fe521e1dfc936656cd4, +it puts 'driver' option if the command line use 'format' option. + +This patch is to solve this bug. + +Signed-off-by: Mike Qiu +Signed-off-by: Kevin Wolf +(cherry picked from commit 6db5f5d68e2ffc430ba0511e23fc36c7363510f1) + +Signed-off-by: Max Reitz +--- + blockdev.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 12 +++++++++--- + 1 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 6710f61..a6563fa 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -342,6 +342,7 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + QDict *bs_opts; + const char *id; + bool has_driver_specific_opts; ++ BlockDriver *drv = NULL; + + translation = BIOS_ATA_TRANSLATION_AUTO; + media = MEDIA_DISK; +@@ -487,7 +488,11 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + return NULL; + } + +- qdict_put(bs_opts, "driver", qstring_from_str(buf)); ++ drv = bdrv_find_whitelisted_format(buf, ro); ++ if (!drv) { ++ error_report("'%s' invalid format", buf); ++ return NULL; ++ } + } + + /* disk I/O throttling */ +@@ -702,12 +707,13 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + } + + QINCREF(bs_opts); +- ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, NULL); ++ ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv); + + if (ret < 0) { + if (ret == -EMEDIUMTYPE) { + error_report("could not open disk image %s: not in %s format", +- file ?: dinfo->id, qdict_get_str(bs_opts, "driver")); ++ file ?: dinfo->id, drv ? drv->format_name : ++ qdict_get_str(bs_opts, "driver")); + } else { + error_report("could not open disk image %s: %s", + file ?: dinfo->id, strerror(-ret)); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Disable-BDRV_O_COPY_ON_READ-for-the-backing-fi.patch b/SOURCES/kvm-block-Disable-BDRV_O_COPY_ON_READ-for-the-backing-fi.patch new file mode 100644 index 0000000..62993de --- /dev/null +++ b/SOURCES/kvm-block-Disable-BDRV_O_COPY_ON_READ-for-the-backing-fi.patch @@ -0,0 +1,57 @@ +From 01a2d73852aa716e9e57ca9726f967f5e801d6f5 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:18 +0100 +Subject: [PATCH 65/87] block: Disable BDRV_O_COPY_ON_READ for the backing file + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-25-git-send-email-kwolf@redhat.com> +Patchwork-id: 55403 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 24/24] block: Disable BDRV_O_COPY_ON_READ for the backing file +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +From: Thibaut LAURENT + +Since commit 0ebd24e0a203cf2852c310b59fbe050190dc6c8c, +bdrv_open_common will throw an error when trying to open a file +read-only with the BDRV_O_COPY_ON_READ flag set. +Although BDRV_O_RDWR is unset for the backing files, +BDRV_O_COPY_ON_READ is still passed on if copy-on-read was requested +for the drive. Let's unset this flag too before opening the backing +file, or bdrv_open_common will fail. + +Signed-off-by: Thibaut LAURENT +Reviewed-by: Benoit Canet +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 87a5debd3161d24a7d4c685e3c0d8765b5d92a74) + +Signed-off-by: Kevin Wolf +--- + block.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 01c11ee..beeb600 100644 +--- a/block.c ++++ b/block.c +@@ -968,7 +968,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + } + + /* backing files always opened read-only */ +- back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT); ++ back_flags = bs->open_flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | ++ BDRV_O_COPY_ON_READ); + + ret = bdrv_open(bs->backing_hd, + *backing_filename ? backing_filename : NULL, options, +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Don-t-copy-backing-file-name-on-error.patch b/SOURCES/kvm-block-Don-t-copy-backing-file-name-on-error.patch new file mode 100644 index 0000000..69a9786 --- /dev/null +++ b/SOURCES/kvm-block-Don-t-copy-backing-file-name-on-error.patch @@ -0,0 +1,68 @@ +From b0f9197ca9efa3768253bfab3b938d06e1d2abc1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 7 Nov 2013 11:19:18 +0100 +Subject: [PATCH 66/87] block: Don't copy backing file name on error + +RH-Author: Kevin Wolf +Message-id: <1383823158-8741-1-git-send-email-kwolf@redhat.com> +Patchwork-id: 55596 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 25/24] block: Don't copy backing file name on error +Bugzilla: 978402 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Miroslav Rezanina + +From: Max Reitz + +bdrv_open_backing_file() tries to copy the backing file name using +pstrcpy directly after calling bdrv_open() to open the backing file +without checking whether that was actually successful. If it was not, +ps->backing_hd->file will probably be NULL and qemu will crash. + +Fix this by moving pstrcpy after checking whether bdrv_open() succeeded. + +Signed-off-by: Max Reitz +Reviewed-by: Benoit Canet +Reviewed-by: Amos Kong +Signed-off-by: Kevin Wolf +(cherry picked from commit 61ed2684539f7f31304e193d7c0e68d57ce6be88) + +Signed-off-by: Kevin Wolf +--- + +Brewing as: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6541865 + +--- + block.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index beeb600..dccdb2c 100644 +--- a/block.c ++++ b/block.c +@@ -974,8 +974,6 @@ 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); +- pstrcpy(bs->backing_file, sizeof(bs->backing_file), +- bs->backing_hd->file->filename); + if (ret < 0) { + bdrv_delete(bs->backing_hd); + bs->backing_hd = NULL; +@@ -983,6 +981,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + error_propagate(errp, local_err); + return ret; + } ++ pstrcpy(bs->backing_file, sizeof(bs->backing_file), ++ bs->backing_hd->file->filename); + return 0; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Don-t-parse-protocol-from-file.filename.patch b/SOURCES/kvm-block-Don-t-parse-protocol-from-file.filename.patch new file mode 100644 index 0000000..031fb67 --- /dev/null +++ b/SOURCES/kvm-block-Don-t-parse-protocol-from-file.filename.patch @@ -0,0 +1,218 @@ +From 8f9ad0991d9dd978f342ff4dcc58a18d8f1a73c4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:58 +0200 +Subject: [PATCH 07/38] block: Don't parse protocol from file.filename + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-8-git-send-email-kwolf@redhat.com> +Patchwork-id: 54194 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 07/32] block: Don't parse protocol from file.filename +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +One of the major reasons for doing something new for -blockdev and +blockdev-add was that the old block layer code parses filenames instead +of just taking them literally. So we should really leave it untouched +when it's passing using the new interfaces (like -drive +file.filename=...). + +This allows opening relative file names that contain a colon. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 98289620e0460fa595581020ab20127da4a2fc44) + +Signed-off-by: Kevin Wolf +--- + block.c | 17 ++++++++++++----- + block/sheepdog.c | 2 +- + include/block/block.h | 3 ++- + qemu-img.c | 4 ++-- + tests/qemu-iotests/051 | 12 ++++++++++++ + tests/qemu-iotests/051.out | 14 ++++++++++++++ + 6 files changed, 43 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 17 ++++++++++++----- + block/sheepdog.c | 2 +- + include/block/block.h | 3 ++- + qemu-img.c | 4 ++-- + tests/qemu-iotests/051 | 12 ++++++++++++ + tests/qemu-iotests/051.out | 14 ++++++++++++++ + 6 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/block.c b/block.c +index 3c869e4..2584ec7 100644 +--- a/block.c ++++ b/block.c +@@ -419,7 +419,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) + { + BlockDriver *drv; + +- drv = bdrv_find_protocol(filename); ++ drv = bdrv_find_protocol(filename, true); + if (drv == NULL) { + return -ENOENT; + } +@@ -484,7 +484,8 @@ static BlockDriver *find_hdev_driver(const char *filename) + return drv; + } + +-BlockDriver *bdrv_find_protocol(const char *filename) ++BlockDriver *bdrv_find_protocol(const char *filename, ++ bool allow_protocol_prefix) + { + BlockDriver *drv1; + char protocol[128]; +@@ -505,9 +506,10 @@ BlockDriver *bdrv_find_protocol(const char *filename) + return drv1; + } + +- if (!path_has_protocol(filename)) { ++ if (!path_has_protocol(filename) || !allow_protocol_prefix) { + return bdrv_find_format("file"); + } ++ + p = strchr(filename, ':'); + assert(p != NULL); + len = p - filename; +@@ -786,6 +788,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + BlockDriverState *bs; + BlockDriver *drv; + const char *drvname; ++ bool allow_protocol_prefix = false; + int ret; + + /* NULL means an empty set of options */ +@@ -802,6 +805,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + filename = qdict_get_try_str(options, "filename"); + } else if (filename && !qdict_haskey(options, "filename")) { + qdict_put(options, "filename", qstring_from_str(filename)); ++ allow_protocol_prefix = true; + } else { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and " + "'filename' options at the same time"); +@@ -815,7 +819,10 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); + qdict_del(options, "driver"); + } else if (filename) { +- drv = bdrv_find_protocol(filename); ++ drv = bdrv_find_protocol(filename, allow_protocol_prefix); ++ if (!drv) { ++ qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol"); ++ } + } else { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "Must specify either driver or file"); +@@ -4770,7 +4777,7 @@ void bdrv_img_create(const char *filename, const char *fmt, + return; + } + +- proto_drv = bdrv_find_protocol(filename); ++ proto_drv = bdrv_find_protocol(filename, true); + if (!proto_drv) { + error_setg(errp, "Unknown protocol '%s'", filename); + return; +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 21a4edf..2758c26 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1510,7 +1510,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) + BlockDriver *drv; + + /* Currently, only Sheepdog backing image is supported. */ +- drv = bdrv_find_protocol(backing_file); ++ drv = bdrv_find_protocol(backing_file, true); + if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { + error_report("backing_file must be a sheepdog image"); + ret = -EINVAL; +diff --git a/include/block/block.h b/include/block/block.h +index db7bc4f..174295b 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -122,7 +122,8 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs); + + void bdrv_init(void); + void bdrv_init_with_whitelist(void); +-BlockDriver *bdrv_find_protocol(const char *filename); ++BlockDriver *bdrv_find_protocol(const char *filename, ++ bool allow_protocol_prefix); + BlockDriver *bdrv_find_format(const char *format_name); + BlockDriver *bdrv_find_whitelisted_format(const char *format_name, + bool readonly); +diff --git a/qemu-img.c b/qemu-img.c +index 673d80f..3b11414 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -238,7 +238,7 @@ static int print_block_option_help(const char *filename, const char *fmt) + return 1; + } + +- proto_drv = bdrv_find_protocol(filename); ++ proto_drv = bdrv_find_protocol(filename, true); + if (!proto_drv) { + error_report("Unknown protocol '%s'", filename); + return 1; +@@ -1261,7 +1261,7 @@ static int img_convert(int argc, char **argv) + goto out; + } + +- proto_drv = bdrv_find_protocol(out_filename); ++ proto_drv = bdrv_find_protocol(out_filename, true); + if (!proto_drv) { + error_report("Unknown protocol '%s'", out_filename); + ret = -1; +diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 +index 8039e23..1cf8bf7 100755 +--- a/tests/qemu-iotests/051 ++++ b/tests/qemu-iotests/051 +@@ -149,6 +149,18 @@ echo + run_qemu -drive file=$TEST_IMG,file.driver=file + run_qemu -drive file=$TEST_IMG,file.driver=qcow2 + ++echo ++echo === Parsing protocol from file name === ++echo ++ ++# Protocol strings are supposed to be parsed from traditional option strings, ++# but not when using driver-specific options. We can distinguish them by the ++# error message for non-existing files. ++ ++run_qemu -hda foo:bar ++run_qemu -drive file=foo:bar ++run_qemu -drive file.filename=foo:bar ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 3d1ac7b..6b3d636 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -169,4 +169,18 @@ Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument + ++ ++=== Parsing protocol from file name === ++ ++Testing: -hda foo:bar ++QEMU_PROG: -hda foo:bar: Unknown protocol ++QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory ++ ++Testing: -drive file=foo:bar ++QEMU_PROG: -drive file=foo:bar: Unknown protocol ++QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory ++ ++Testing: -drive file.filename=foo:bar ++QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: No such file or directory ++ + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Error-parameter-for-create-functions.patch b/SOURCES/kvm-block-Error-parameter-for-create-functions.patch new file mode 100644 index 0000000..0f68f57 --- /dev/null +++ b/SOURCES/kvm-block-Error-parameter-for-create-functions.patch @@ -0,0 +1,380 @@ +From 8f07e694eb932e0f3d50ad1083155b314e0162ca Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:12 +0100 +Subject: [PATCH 19/87] block: Error parameter for create functions + +RH-Author: Max Reitz +Message-id: <1383604354-12743-22-git-send-email-mreitz@redhat.com> +Patchwork-id: 55321 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 21/43] block: Error parameter for create functions +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Add an Error ** parameter to bdrv_create and its associated functions to +allow more specific error messages. + +Signed-off-by: Max Reitz +(cherry picked from commit cc84d90ff54c025190dbe49ec5fea1268217c5f2) + +Signed-off-by: Max Reitz + +Conflicts: + block/raw.c + block/raw_bsd.c + +Conflicts because raw_bsd.c does not exist downstream; instead, there is +raw.c. +--- + block.c | 80 +++++++++++++++++++++++++++++++++++---------------- + block/cow.c | 4 ++- + block/qcow.c | 4 ++- + block/qcow2.c | 2 +- + block/qed.c | 4 ++- + block/raw.c | 10 ++++++- + block/vvfat.c | 4 ++- + include/block/block.h | 5 ++-- + qemu-img.c | 16 ++++------- + 9 files changed, 86 insertions(+), 43 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 80 ++++++++++++++++++++++++++++++++++-------------- + block/cow.c | 4 ++- + block/qcow.c | 4 ++- + block/qcow2.c | 2 +- + block/qed.c | 4 ++- + block/raw.c | 10 +++++- + block/vvfat.c | 4 ++- + include/block/block.h | 5 ++- + qemu-img.c | 16 +++------- + 9 files changed, 86 insertions(+), 43 deletions(-) + +diff --git a/block.c b/block.c +index cb99faf..c2b6930 100644 +--- a/block.c ++++ b/block.c +@@ -366,18 +366,26 @@ typedef struct CreateCo { + char *filename; + QEMUOptionParameter *options; + int ret; ++ Error *err; + } CreateCo; + + static void coroutine_fn bdrv_create_co_entry(void *opaque) + { ++ Error *local_err = NULL; ++ int ret; ++ + CreateCo *cco = opaque; + assert(cco->drv); + +- cco->ret = cco->drv->bdrv_create(cco->filename, cco->options, NULL); ++ ret = cco->drv->bdrv_create(cco->filename, cco->options, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(&cco->err, local_err); ++ } ++ cco->ret = ret; + } + + int bdrv_create(BlockDriver *drv, const char* filename, +- QEMUOptionParameter *options) ++ QEMUOptionParameter *options, Error **errp) + { + int ret; + +@@ -387,9 +395,11 @@ int bdrv_create(BlockDriver *drv, const char* filename, + .filename = g_strdup(filename), + .options = options, + .ret = NOT_DONE, ++ .err = NULL, + }; + + if (!drv->bdrv_create) { ++ error_setg(errp, "Driver '%s' does not support image creation", drv->format_name); + ret = -ENOTSUP; + goto out; + } +@@ -406,22 +416,37 @@ int bdrv_create(BlockDriver *drv, const char* filename, + } + + ret = cco.ret; ++ if (ret < 0) { ++ if (error_is_set(&cco.err)) { ++ error_propagate(errp, cco.err); ++ } else { ++ error_setg_errno(errp, -ret, "Could not create image"); ++ } ++ } + + out: + g_free(cco.filename); + return ret; + } + +-int bdrv_create_file(const char* filename, QEMUOptionParameter *options) ++int bdrv_create_file(const char* filename, QEMUOptionParameter *options, ++ Error **errp) + { + BlockDriver *drv; ++ Error *local_err = NULL; ++ int ret; + + drv = bdrv_find_protocol(filename, true); + if (drv == NULL) { ++ error_setg(errp, "Could not find protocol for file '%s'", filename); + return -ENOENT; + } + +- return bdrv_create(drv, filename, options); ++ ret = bdrv_create(drv, filename, options, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } ++ return ret; + } + + /* +@@ -1055,11 +1080,14 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + drv->format_name); + } + +- ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options); ++ ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options, &local_err); + free_option_parameters(create_options); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not create temporary overlay " +- "'%s'", tmp_filename); ++ "'%s': %s", tmp_filename, ++ error_get_pretty(local_err)); ++ error_free(local_err); ++ local_err = NULL; + goto fail; + } + +@@ -4755,6 +4783,7 @@ void bdrv_img_create(const char *filename, const char *fmt, + BlockDriverState *bs = NULL; + BlockDriver *drv, *proto_drv; + BlockDriver *backing_drv = NULL; ++ Error *local_err = NULL; + int ret = 0; + + /* Find driver and parse its options */ +@@ -4841,10 +4870,13 @@ void bdrv_img_create(const char *filename, const char *fmt, + bs = bdrv_new(""); + + ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags, +- backing_drv, NULL); ++ backing_drv, &local_err); + if (ret < 0) { +- error_setg_errno(errp, -ret, "Could not open '%s'", +- backing_file->value.s); ++ 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); +@@ -4863,22 +4895,19 @@ void bdrv_img_create(const char *filename, const char *fmt, + print_option_parameters(param); + puts(""); + } +- ret = bdrv_create(drv, filename, param); +- if (ret < 0) { +- if (ret == -ENOTSUP) { +- error_setg(errp,"Formatting or formatting option not supported for " +- "file format '%s'", fmt); +- } else if (ret == -EFBIG) { +- const char *cluster_size_hint = ""; +- if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) { +- cluster_size_hint = " (try using a larger cluster size)"; +- } +- error_setg(errp, "The image size is too large for file format '%s'%s", +- fmt, cluster_size_hint); +- } else { +- error_setg(errp, "%s: error while creating %s: %s", filename, fmt, +- strerror(-ret)); ++ ret = bdrv_create(drv, filename, param, &local_err); ++ if (ret == -EFBIG) { ++ /* This is generally a better message than whatever the driver would ++ * deliver (especially because of the cluster_size_hint), since that ++ * is most probably not much different from "image too large". */ ++ const char *cluster_size_hint = ""; ++ if (get_option_parameter(create_options, BLOCK_OPT_CLUSTER_SIZE)) { ++ cluster_size_hint = " (try using a larger cluster size)"; + } ++ error_setg(errp, "The image size is too large for file format '%s'" ++ "%s", fmt, cluster_size_hint); ++ error_free(local_err); ++ local_err = NULL; + } + + out: +@@ -4888,6 +4917,9 @@ out: + if (bs) { + bdrv_delete(bs); + } ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + } + + AioContext *bdrv_get_aio_context(BlockDriverState *bs) +diff --git a/block/cow.c b/block/cow.c +index 8e00f8f..cd78129 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -316,8 +316,10 @@ static int cow_create(const char *filename, QEMUOptionParameter *options, + options++; + } + +- ret = bdrv_create_file(filename, options); ++ ret = bdrv_create_file(filename, options, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/qcow.c b/block/qcow.c +index 41a578c..6d029cc 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -684,8 +684,10 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options, + options++; + } + +- ret = bdrv_create_file(filename, options); ++ ret = bdrv_create_file(filename, options, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/qcow2.c b/block/qcow2.c +index a2fca7a..027d210 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1364,7 +1364,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + uint8_t* refcount_table; + int ret; + +- ret = bdrv_create_file(filename, options); ++ ret = bdrv_create_file(filename, options, NULL); + if (ret < 0) { + return ret; + } +diff --git a/block/qed.c b/block/qed.c +index fa35fe2..7b13bb5 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -555,8 +555,10 @@ static int qed_create(const char *filename, uint32_t cluster_size, + int ret = 0; + BlockDriverState *bs = NULL; + +- ret = bdrv_create_file(filename, NULL); ++ ret = bdrv_create_file(filename, NULL, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/raw.c b/block/raw.c +index f92c04e..50073b6 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -108,7 +108,15 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, + static int raw_create(const char *filename, QEMUOptionParameter *options, + Error **errp) + { +- return bdrv_create_file(filename, options); ++ Error *local_err = NULL; ++ int ret; ++ ++ ret = bdrv_create_file(filename, options, &local_err); ++ if (error_is_set(&local_err)) { ++ qerror_report_err(local_err); ++ error_free(local_err); ++ } ++ return ret; + } + + static QEMUOptionParameter raw_create_options[] = { +diff --git a/block/vvfat.c b/block/vvfat.c +index a385b6f..cb45687 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2928,8 +2928,10 @@ static int enable_write_target(BDRVVVFATState *s) + set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); + set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); + +- ret = bdrv_create(bdrv_qcow, s->qcow_filename, options); ++ ret = bdrv_create(bdrv_qcow, s->qcow_filename, options, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto err; + } + +diff --git a/include/block/block.h b/include/block/block.h +index 168d8a8..fac1282 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -152,8 +152,9 @@ BlockDriver *bdrv_find_format(const char *format_name); + BlockDriver *bdrv_find_whitelisted_format(const char *format_name, + bool readonly); + int bdrv_create(BlockDriver *drv, const char* filename, +- QEMUOptionParameter *options); +-int bdrv_create_file(const char* filename, QEMUOptionParameter *options); ++ QEMUOptionParameter *options, Error **errp); ++int bdrv_create_file(const char* filename, QEMUOptionParameter *options, ++ Error **errp); + BlockDriverState *bdrv_new(const char *device_name); + void bdrv_make_anon(BlockDriverState *bs); + void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old); +diff --git a/qemu-img.c b/qemu-img.c +index d7d1244..9fda8cf 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1136,6 +1136,7 @@ static int img_convert(int argc, char **argv) + float local_progress = 0; + int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */ + bool quiet = false; ++ Error *local_err = NULL; + + fmt = NULL; + out_fmt = "raw"; +@@ -1338,18 +1339,11 @@ static int img_convert(int argc, char **argv) + + if (!skip_create) { + /* Create the new image */ +- ret = bdrv_create(drv, out_filename, param); ++ ret = bdrv_create(drv, out_filename, param, &local_err); + if (ret < 0) { +- if (ret == -ENOTSUP) { +- error_report("Formatting not supported for file format '%s'", +- out_fmt); +- } else if (ret == -EFBIG) { +- error_report("The image size is too large for file format '%s'", +- out_fmt); +- } else { +- error_report("%s: error while converting %s: %s", +- out_filename, out_fmt, strerror(-ret)); +- } ++ error_report("%s: error while converting %s: %s", ++ out_filename, out_fmt, error_get_pretty(local_err)); ++ error_free(local_err); + goto out; + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Error-parameter-for-open-functions.patch b/SOURCES/kvm-block-Error-parameter-for-open-functions.patch new file mode 100644 index 0000000..e8833c7 --- /dev/null +++ b/SOURCES/kvm-block-Error-parameter-for-open-functions.patch @@ -0,0 +1,940 @@ +From 8d4ddeff8f248b561affa518acc19739b76e2f08 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:11 +0100 +Subject: [PATCH 18/87] block: Error parameter for open functions + +RH-Author: Max Reitz +Message-id: <1383604354-12743-21-git-send-email-mreitz@redhat.com> +Patchwork-id: 55320 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 20/43] block: Error parameter for open functions +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Add an Error ** parameter to bdrv_open, bdrv_file_open and associated +functions to allow more specific error messages. + +Signed-off-by: Max Reitz +(cherry picked from commit 34b5d2c68eb4082c288e70fb99c61af8f7b96fde) + +Signed-off-by: Max Reitz + +Conflicts: + block/blkverify.c + block/vmdk.c + block/vvfat.c + blockdev.c + hw/block/xen_disk.c + qemu-io.c + +All files conflict because the series "Implement reference count for +BlockDriverState" has not yet been backported which "replaces" +bdrv_delete by bdrv_unref. + +blockdev.c conflicts because the series "block: drive-backup live backup +command command" has not yet been backported. + +qemu-io.c conflicts because the series "Make qemu-io commands available +in the monitor" has not yet been backported (esp. commit 734c3b85c). +--- + block.c | 100 ++++++++++++++++++++++++++++++++------------------ + block/blkdebug.c | 4 +- + block/blkverify.c | 8 +++- + block/cow.c | 5 ++- + block/mirror.c | 5 ++- + block/qcow.c | 5 ++- + block/qcow2.c | 4 +- + block/qed.c | 6 ++- + block/sheepdog.c | 10 ++++- + block/vmdk.c | 11 +++++- + block/vvfat.c | 6 ++- + blockdev.c | 26 ++++++------- + hw/block/xen_disk.c | 7 +++- + include/block/block.h | 6 +-- + qemu-img.c | 21 +++++++---- + qemu-io.c | 14 +++++-- + qemu-nbd.c | 6 ++- + 17 files changed, 161 insertions(+), 83 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 100 +++++++++++++++++++++++++++++++----------------- + block/blkdebug.c | 4 +- + block/blkverify.c | 8 +++- + block/cow.c | 5 ++- + block/mirror.c | 5 +- + block/qcow.c | 5 ++- + block/qcow2.c | 4 +- + block/qed.c | 6 ++- + block/sheepdog.c | 10 ++++- + block/vmdk.c | 11 ++++- + block/vvfat.c | 6 ++- + blockdev.c | 26 +++++------- + hw/block/xen_disk.c | 7 +++- + include/block/block.h | 6 +- + qemu-img.c | 21 +++++++--- + qemu-io.c | 14 +++++-- + qemu-nbd.c | 6 ++- + 17 files changed, 161 insertions(+), 83 deletions(-) + +diff --git a/block.c b/block.c +index 0cb5ac9..cb99faf 100644 +--- a/block.c ++++ b/block.c +@@ -524,7 +524,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, + } + + static int find_image_format(BlockDriverState *bs, const char *filename, +- BlockDriver **pdrv) ++ BlockDriver **pdrv, Error **errp) + { + int score, score_max; + BlockDriver *drv1, *drv; +@@ -535,6 +535,7 @@ static int find_image_format(BlockDriverState *bs, const char *filename, + if (bs->sg || !bdrv_is_inserted(bs) || bdrv_getlength(bs) == 0) { + drv = bdrv_find_format("raw"); + if (!drv) { ++ error_setg(errp, "Could not find raw image format"); + ret = -ENOENT; + } + *pdrv = drv; +@@ -543,6 +544,8 @@ static int find_image_format(BlockDriverState *bs, const char *filename, + + ret = bdrv_pread(bs, 0, buf, sizeof(buf)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read image for determining its " ++ "format"); + *pdrv = NULL; + return ret; + } +@@ -559,6 +562,8 @@ static int find_image_format(BlockDriverState *bs, const char *filename, + } + } + if (!drv) { ++ error_setg(errp, "Could not determine image format: No compatible " ++ "driver found"); + ret = -ENOENT; + } + *pdrv = drv; +@@ -678,10 +683,11 @@ static int bdrv_open_flags(BlockDriverState *bs, int flags) + * Removes all processed options from *options. + */ + static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, +- QDict *options, int flags, BlockDriver *drv) ++ QDict *options, int flags, BlockDriver *drv, Error **errp) + { + int ret, open_flags; + const char *filename; ++ Error *local_err = NULL; + + assert(drv != NULL); + assert(bs->file == NULL); +@@ -710,6 +716,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + bs->read_only = !(open_flags & BDRV_O_RDWR); + + if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) { ++ error_setg(errp, "Driver '%s' is not whitelisted", drv->format_name); + return -ENOTSUP; + } + +@@ -733,26 +740,33 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + if (drv->bdrv_file_open) { + assert(file == NULL); + assert(drv->bdrv_parse_filename || filename != NULL); +- ret = drv->bdrv_file_open(bs, options, open_flags, NULL); ++ ret = drv->bdrv_file_open(bs, options, open_flags, &local_err); + } else { + if (file == NULL) { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't use '%s' as a " +- "block driver for the protocol level", +- drv->format_name); ++ error_setg(errp, "Can't use '%s' as a block driver for the " ++ "protocol level", drv->format_name); + ret = -EINVAL; + goto free_and_fail; + } + assert(file != NULL); + bs->file = file; +- ret = drv->bdrv_open(bs, options, open_flags, NULL); ++ ret = drv->bdrv_open(bs, options, open_flags, &local_err); + } + + if (ret < 0) { ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } else if (filename) { ++ error_setg_errno(errp, -ret, "Could not open '%s'", filename); ++ } else { ++ error_setg_errno(errp, -ret, "Could not open image"); ++ } + goto free_and_fail; + } + + ret = refresh_total_sectors(bs, bs->total_sectors); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not refresh total sector count"); + goto free_and_fail; + } + +@@ -781,12 +795,13 @@ free_and_fail: + * dictionary, it needs to use QINCREF() before calling bdrv_file_open. + */ + int bdrv_file_open(BlockDriverState **pbs, const char *filename, +- QDict *options, int flags) ++ QDict *options, int flags, Error **errp) + { + BlockDriverState *bs; + BlockDriver *drv; + const char *drvname; + bool allow_protocol_prefix = false; ++ Error *local_err = NULL; + int ret; + + /* NULL means an empty set of options */ +@@ -805,8 +820,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + qdict_put(options, "filename", qstring_from_str(filename)); + allow_protocol_prefix = true; + } else { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and " +- "'filename' options at the same time"); ++ error_setg(errp, "Can't specify 'file' and 'filename' options at the " ++ "same time"); + ret = -EINVAL; + goto fail; + } +@@ -815,53 +830,53 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, + drvname = qdict_get_try_str(options, "driver"); + if (drvname) { + drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); ++ if (!drv) { ++ error_setg(errp, "Unknown driver '%s'", drvname); ++ } + qdict_del(options, "driver"); + } else if (filename) { + drv = bdrv_find_protocol(filename, allow_protocol_prefix); + if (!drv) { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol"); ++ error_setg(errp, "Unknown protocol"); + } + } else { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, +- "Must specify either driver or file"); ++ error_setg(errp, "Must specify either driver or file"); + drv = NULL; + } + + if (!drv) { ++ /* errp has been set already */ + ret = -ENOENT; + goto fail; + } + + /* Parse the filename and open it */ + if (drv->bdrv_parse_filename && filename) { +- Error *local_err = NULL; + drv->bdrv_parse_filename(filename, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } + qdict_del(options, "filename"); + } else if (!drv->bdrv_parse_filename && !filename) { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, +- "The '%s' block driver requires a file name", +- drv->format_name); ++ error_setg(errp, "The '%s' block driver requires a file name", ++ drv->format_name); + ret = -EINVAL; + goto fail; + } + +- ret = bdrv_open_common(bs, NULL, options, flags, drv); ++ ret = bdrv_open_common(bs, NULL, options, flags, drv, &local_err); + if (ret < 0) { ++ error_propagate(errp, local_err); + goto fail; + } + + /* Check if any unknown options were used */ + if (qdict_size(options) != 0) { + const QDictEntry *entry = qdict_first(options); +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block protocol '%s' doesn't " +- "support the option '%s'", +- drv->format_name, entry->key); ++ error_setg(errp, "Block protocol '%s' doesn't support the option '%s'", ++ drv->format_name, entry->key); + ret = -EINVAL; + goto fail; + } +@@ -888,11 +903,12 @@ fail: + * function (even on failure), so if the caller intends to reuse the dictionary, + * it needs to use QINCREF() before calling bdrv_file_open. + */ +-int bdrv_open_backing_file(BlockDriverState *bs, QDict *options) ++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) { + QDECREF(options); +@@ -925,11 +941,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options) + + ret = bdrv_open(bs->backing_hd, + *backing_filename ? backing_filename : NULL, options, +- back_flags, back_drv); ++ back_flags, back_drv, &local_err); + if (ret < 0) { + bdrv_delete(bs->backing_hd); + bs->backing_hd = NULL; + bs->open_flags |= BDRV_O_NO_BACKING; ++ error_propagate(errp, local_err); + return ret; + } + return 0; +@@ -963,7 +980,7 @@ static void extract_subqdict(QDict *src, QDict **dst, const char *start) + * dictionary, it needs to use QINCREF() before calling bdrv_open. + */ + int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, +- int flags, BlockDriver *drv) ++ int flags, BlockDriver *drv, Error **errp) + { + int ret; + /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */ +@@ -971,6 +988,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + BlockDriverState *file = NULL; + QDict *file_options = NULL; + const char *drvname; ++ Error *local_err = NULL; + + /* NULL means an empty set of options */ + if (options == NULL) { +@@ -989,7 +1007,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + char backing_filename[PATH_MAX]; + + if (qdict_size(options) != 0) { +- error_report("Can't use snapshot=on with driver-specific options"); ++ error_setg(errp, "Can't use snapshot=on with driver-specific options"); + ret = -EINVAL; + goto fail; + } +@@ -1000,7 +1018,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + + /* if there is a backing file, use it */ + bs1 = bdrv_new(""); +- ret = bdrv_open(bs1, filename, NULL, 0, drv); ++ ret = bdrv_open(bs1, filename, NULL, 0, drv, &local_err); + if (ret < 0) { + bdrv_delete(bs1); + goto fail; +@@ -1011,6 +1029,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + + ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not get temporary filename"); + goto fail; + } + +@@ -1019,6 +1038,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + snprintf(backing_filename, sizeof(backing_filename), + "%s", filename); + } else if (!realpath(filename, backing_filename)) { ++ error_setg_errno(errp, errno, "Could not resolve path '%s'", filename); + ret = -errno; + goto fail; + } +@@ -1038,6 +1058,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options); + free_option_parameters(create_options); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not create temporary overlay " ++ "'%s'", tmp_filename); + goto fail; + } + +@@ -1054,7 +1076,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + extract_subqdict(options, &file_options, "file."); + + ret = bdrv_file_open(&file, filename, file_options, +- bdrv_open_flags(bs, flags | BDRV_O_UNMAP)); ++ bdrv_open_flags(bs, flags | BDRV_O_UNMAP), &local_err); + if (ret < 0) { + goto fail; + } +@@ -1067,7 +1089,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + } + + if (!drv) { +- ret = find_image_format(file, filename, &drv); ++ ret = find_image_format(file, filename, &drv, &local_err); + } + + if (!drv) { +@@ -1075,7 +1097,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + } + + /* Open the image */ +- ret = bdrv_open_common(bs, file, options, flags, drv); ++ ret = bdrv_open_common(bs, file, options, flags, drv, &local_err); + if (ret < 0) { + goto unlink_and_fail; + } +@@ -1090,7 +1112,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + QDict *backing_options; + + extract_subqdict(options, &backing_options, "backing."); +- ret = bdrv_open_backing_file(bs, backing_options); ++ ret = bdrv_open_backing_file(bs, backing_options, &local_err); + if (ret < 0) { + goto close_and_fail; + } +@@ -1099,9 +1121,9 @@ int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, + /* Check if any unknown options were used */ + if (qdict_size(options) != 0) { + const QDictEntry *entry = qdict_first(options); +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by " +- "device '%s' doesn't support the option '%s'", +- drv->format_name, bs->device_name, entry->key); ++ error_setg(errp, "Block format '%s' used by device '%s' doesn't " ++ "support the option '%s'", drv->format_name, bs->device_name, ++ entry->key); + + ret = -EINVAL; + goto close_and_fail; +@@ -1130,11 +1152,17 @@ fail: + QDECREF(bs->options); + QDECREF(options); + bs->options = NULL; ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + return ret; + + close_and_fail: + bdrv_close(bs); + QDECREF(options); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + return ret; + } + +@@ -4813,7 +4841,7 @@ void bdrv_img_create(const char *filename, const char *fmt, + bs = bdrv_new(""); + + ret = bdrv_open(bs, backing_file->value.s, NULL, back_flags, +- backing_drv); ++ backing_drv, NULL); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not open '%s'", + backing_file->value.s); +diff --git a/block/blkdebug.c b/block/blkdebug.c +index 114c4c9..eda2810 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -384,8 +384,10 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags, + goto fail; + } + +- ret = bdrv_file_open(&bs->file, filename, NULL, flags); ++ ret = bdrv_file_open(&bs->file, filename, NULL, flags, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto fail; + } + +diff --git a/block/blkverify.c b/block/blkverify.c +index 5d716bb..cceb88f 100644 +--- a/block/blkverify.c ++++ b/block/blkverify.c +@@ -141,8 +141,10 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + goto fail; + } + +- ret = bdrv_file_open(&bs->file, raw, NULL, flags); ++ ret = bdrv_file_open(&bs->file, raw, NULL, flags, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto fail; + } + +@@ -154,8 +156,10 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags, + } + + s->test_file = bdrv_new(""); +- ret = bdrv_open(s->test_file, filename, NULL, flags, NULL); ++ ret = bdrv_open(s->test_file, filename, NULL, flags, NULL, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + bdrv_delete(s->test_file); + s->test_file = NULL; + goto fail; +diff --git a/block/cow.c b/block/cow.c +index c1d2dc8..8e00f8f 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -302,6 +302,7 @@ static int cow_create(const char *filename, QEMUOptionParameter *options, + struct stat st; + int64_t image_sectors = 0; + const char *image_filename = NULL; ++ Error *local_err = NULL; + int ret; + BlockDriverState *cow_bs; + +@@ -320,8 +321,10 @@ static int cow_create(const char *filename, QEMUOptionParameter *options, + return ret; + } + +- ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR); ++ ret = bdrv_file_open(&cow_bs, filename, NULL, BDRV_O_RDWR, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/mirror.c b/block/mirror.c +index dad1e3e..6fa733e 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -505,14 +505,15 @@ static void mirror_iostatus_reset(BlockJob *job) + static void mirror_complete(BlockJob *job, Error **errp) + { + MirrorBlockJob *s = container_of(job, MirrorBlockJob, common); ++ Error *local_err = NULL; + int ret; + +- ret = bdrv_open_backing_file(s->target, NULL); ++ ret = bdrv_open_backing_file(s->target, NULL, &local_err); + if (ret < 0) { + char backing_filename[PATH_MAX]; + bdrv_get_full_backing_filename(s->target, backing_filename, + sizeof(backing_filename)); +- error_setg_file_open(errp, -ret, backing_filename); ++ error_propagate(errp, local_err); + return; + } + if (!s->synced) { +diff --git a/block/qcow.c b/block/qcow.c +index 1a6926f..41a578c 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -668,6 +668,7 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options, + int64_t total_size = 0; + const char *backing_file = NULL; + int flags = 0; ++ Error *local_err = NULL; + int ret; + BlockDriverState *qcow_bs; + +@@ -688,8 +689,10 @@ static int qcow_create(const char *filename, QEMUOptionParameter *options, + return ret; + } + +- ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR); ++ ret = bdrv_file_open(&qcow_bs, filename, NULL, BDRV_O_RDWR, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/qcow2.c b/block/qcow2.c +index b6e50af..a2fca7a 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1369,7 +1369,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + return ret; + } + +- ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR); ++ ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, NULL); + if (ret < 0) { + return ret; + } +@@ -1422,7 +1422,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + BlockDriver* drv = bdrv_find_format("qcow2"); + assert(drv != NULL); + ret = bdrv_open(bs, filename, NULL, +- BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv); ++ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, NULL); + if (ret < 0) { + goto out; + } +diff --git a/block/qed.c b/block/qed.c +index c56b5e2..fa35fe2 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -551,6 +551,7 @@ static int qed_create(const char *filename, uint32_t cluster_size, + QEDHeader le_header; + uint8_t *l1_table = NULL; + size_t l1_size = header.cluster_size * header.table_size; ++ Error *local_err = NULL; + int ret = 0; + BlockDriverState *bs = NULL; + +@@ -559,8 +560,11 @@ static int qed_create(const char *filename, uint32_t cluster_size, + return ret; + } + +- ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB); ++ ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR | BDRV_O_CACHE_WB, ++ &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 952d703..e7c4448 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -1418,10 +1418,13 @@ static int sd_prealloc(const char *filename) + uint32_t idx, max_idx; + int64_t vdi_size; + void *buf = g_malloc0(SD_DATA_OBJ_SIZE); ++ Error *local_err = NULL; + int ret; + +- ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR); ++ ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto out; + } + +@@ -1466,6 +1469,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, + char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN]; + uint32_t snapid; + bool prealloc = false; ++ Error *local_err = NULL; + + s = g_malloc0(sizeof(BDRVSheepdogState)); + +@@ -1519,8 +1523,10 @@ static int sd_create(const char *filename, QEMUOptionParameter *options, + goto out; + } + +- ret = bdrv_file_open(&bs, backing_file, NULL, 0); ++ ret = bdrv_file_open(&bs, backing_file, NULL, 0, &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + goto out; + } + +diff --git a/block/vmdk.c b/block/vmdk.c +index fa64f05..213901f 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -697,6 +697,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + int64_t flat_offset; + char extent_path[PATH_MAX]; + BlockDriverState *extent_file; ++ Error *local_err = NULL; + + while (*p) { + /* parse extent line: +@@ -726,8 +727,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + + path_combine(extent_path, sizeof(extent_path), + desc_file_path, fname); +- ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags); ++ ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags, ++ &local_err); + if (ret) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return ret; + } + +@@ -1591,6 +1595,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + "ddb.geometry.heads = \"%d\"\n" + "ddb.geometry.sectors = \"63\"\n" + "ddb.adapterType = \"%s\"\n"; ++ Error *local_err = NULL; + + if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { + return -EINVAL; +@@ -1653,8 +1658,10 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + } + if (backing_file) { + BlockDriverState *bs = bdrv_new(""); +- ret = bdrv_open(bs, backing_file, NULL, 0, NULL); ++ ret = bdrv_open(bs, backing_file, NULL, 0, NULL, &local_err); + if (ret != 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + bdrv_delete(bs); + return ret; + } +diff --git a/block/vvfat.c b/block/vvfat.c +index bb3b0b6..a385b6f 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2910,6 +2910,7 @@ static int enable_write_target(BDRVVVFATState *s) + { + BlockDriver *bdrv_qcow; + QEMUOptionParameter *options; ++ Error *local_err = NULL; + int ret; + int size = sector2cluster(s, s->sector_count); + s->used_clusters = calloc(size, 1); +@@ -2935,8 +2936,11 @@ static int enable_write_target(BDRVVVFATState *s) + s->qcow = bdrv_new(""); + + ret = bdrv_open(s->qcow, s->qcow_filename, NULL, +- BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow); ++ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow, ++ &local_err); + if (ret < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + bdrv_delete(s->qcow); + goto err; + } +diff --git a/blockdev.c b/blockdev.c +index a6563fa..2fb6d83 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -707,17 +707,11 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + } + + QINCREF(bs_opts); +- ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv); ++ ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error); + + if (ret < 0) { +- if (ret == -EMEDIUMTYPE) { +- error_report("could not open disk image %s: not in %s format", +- file ?: dinfo->id, drv ? drv->format_name : +- qdict_get_str(bs_opts, "driver")); +- } else { +- error_report("could not open disk image %s: %s", +- file ?: dinfo->id, strerror(-ret)); +- } ++ error_report("could not open disk image %s: %s", ++ file ?: dinfo->id, error_get_pretty(error)); + goto err; + } + +@@ -958,9 +952,9 @@ static void external_snapshot_prepare(BlkTransactionStates *common, + /* TODO Inherit bs->options or only take explicit options with an + * extended QMP command? */ + ret = bdrv_open(states->new_bs, new_image_file, NULL, +- flags | BDRV_O_NO_BACKING, drv); ++ flags | BDRV_O_NO_BACKING, drv, &local_err); + if (ret != 0) { +- error_setg_file_open(errp, -ret, new_image_file); ++ error_propagate(errp, local_err); + } + } + +@@ -1124,11 +1118,12 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, + int bdrv_flags, BlockDriver *drv, + const char *password, Error **errp) + { ++ Error *local_err = NULL; + int ret; + +- ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv); ++ ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv, &local_err); + if (ret < 0) { +- error_setg_file_open(errp, -ret, filename); ++ error_propagate(errp, local_err); + return; + } + +@@ -1538,10 +1533,11 @@ void qmp_drive_mirror(const char *device, const char *target, + * file. + */ + target_bs = bdrv_new(""); +- ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv); ++ ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv, ++ &local_err); + if (ret < 0) { + bdrv_delete(target_bs); +- error_setg_file_open(errp, -ret, target); ++ error_propagate(errp, local_err); + return; + } + +diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c +index 247f32f..2d4d263 100644 +--- a/hw/block/xen_disk.c ++++ b/hw/block/xen_disk.c +@@ -797,10 +797,15 @@ static int blk_connect(struct XenDevice *xendev) + xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n"); + blkdev->bs = bdrv_new(blkdev->dev); + if (blkdev->bs) { ++ Error *local_err = NULL; + BlockDriver *drv = bdrv_find_whitelisted_format(blkdev->fileproto, + readonly); + if (bdrv_open(blkdev->bs, +- blkdev->filename, NULL, qflags, drv) != 0) { ++ blkdev->filename, NULL, qflags, drv, &local_err) != 0) ++ { ++ xen_be_printf(&blkdev->xendev, 0, "error: %s\n", ++ error_get_pretty(local_err)); ++ error_free(local_err); + bdrv_delete(blkdev->bs); + blkdev->bs = NULL; + } +diff --git a/include/block/block.h b/include/block/block.h +index 39770a3..168d8a8 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -162,10 +162,10 @@ void bdrv_delete(BlockDriverState *bs); + int bdrv_parse_cache_flags(const char *mode, int *flags); + int bdrv_parse_discard_flags(const char *mode, int *flags); + int bdrv_file_open(BlockDriverState **pbs, const char *filename, +- QDict *options, int flags); +-int bdrv_open_backing_file(BlockDriverState *bs, QDict *options); ++ QDict *options, int flags, Error **errp); ++int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp); + int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options, +- int flags, BlockDriver *drv); ++ int flags, BlockDriver *drv, Error **errp); + BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue, + BlockDriverState *bs, int flags); + int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp); +diff --git a/qemu-img.c b/qemu-img.c +index 8fcea44..d7d1244 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -264,6 +264,7 @@ static BlockDriverState *bdrv_new_open(const char *filename, + BlockDriverState *bs; + BlockDriver *drv; + char password[256]; ++ Error *local_err = NULL; + int ret; + + bs = bdrv_new("image"); +@@ -278,9 +279,11 @@ static BlockDriverState *bdrv_new_open(const char *filename, + drv = NULL; + } + +- ret = bdrv_open(bs, filename, NULL, flags, drv); ++ ret = bdrv_open(bs, filename, NULL, flags, drv, &local_err); + if (ret < 0) { +- error_report("Could not open '%s': %s", filename, strerror(-ret)); ++ error_report("Could not open '%s': %s", filename, ++ error_get_pretty(local_err)); ++ error_free(local_err); + goto fail; + } + +@@ -2266,6 +2269,7 @@ static int img_rebase(int argc, char **argv) + int unsafe = 0; + int progress = 0; + bool quiet = false; ++ Error *local_err = NULL; + + /* Parse commandline parameters */ + fmt = NULL; +@@ -2369,18 +2373,21 @@ static int img_rebase(int argc, char **argv) + bs_old_backing = bdrv_new("old_backing"); + bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name)); + ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS, +- old_backing_drv); ++ old_backing_drv, &local_err); + if (ret) { +- error_report("Could not open old backing file '%s'", backing_name); ++ error_report("Could not open old backing file '%s': %s", ++ backing_name, error_get_pretty(local_err)); ++ error_free(local_err); + goto out; + } + if (out_baseimg[0]) { + bs_new_backing = bdrv_new("new_backing"); + ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS, +- new_backing_drv); ++ new_backing_drv, &local_err); + if (ret) { +- error_report("Could not open new backing file '%s'", +- out_baseimg); ++ error_report("Could not open new backing file '%s': %s", ++ out_baseimg, error_get_pretty(local_err)); ++ error_free(local_err); + goto out; + } + } +diff --git a/qemu-io.c b/qemu-io.c +index bdcce7f..116bb1b 100644 +--- a/qemu-io.c ++++ b/qemu-io.c +@@ -1764,21 +1764,27 @@ static const cmdinfo_t close_cmd = { + + static int openfile(char *name, int flags, int growable) + { ++ Error *local_err = NULL; ++ + if (bs) { + fprintf(stderr, "file open already, try 'help close'\n"); + return 1; + } + + if (growable) { +- if (bdrv_file_open(&bs, name, NULL, flags)) { +- fprintf(stderr, "%s: can't open device %s\n", progname, name); ++ if (bdrv_file_open(&bs, name, NULL, flags, &local_err)) { ++ fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, ++ error_get_pretty(local_err)); ++ error_free(local_err); + return 1; + } + } else { + bs = bdrv_new("hda"); + +- if (bdrv_open(bs, name, NULL, flags, NULL) < 0) { +- fprintf(stderr, "%s: can't open device %s\n", progname, name); ++ if (bdrv_open(bs, name, NULL, flags, NULL, &local_err) < 0) { ++ fprintf(stderr, "%s: can't open device %s: %s\n", progname, name, ++ error_get_pretty(local_err)); ++ error_free(local_err); + bdrv_delete(bs); + bs = NULL; + return 1; +diff --git a/qemu-nbd.c b/qemu-nbd.c +index 9c31d45..c1b395d 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -354,6 +354,7 @@ int main(int argc, char **argv) + #endif + pthread_t client_thread; + const char *fmt = NULL; ++ Error *local_err = NULL; + + /* The client thread uses SIGTERM to interrupt the server. A signal + * handler ensures that "qemu-nbd -v -c" exits with a nice status code. +@@ -572,10 +573,11 @@ int main(int argc, char **argv) + + bs = bdrv_new("hda"); + srcpath = argv[optind]; +- ret = bdrv_open(bs, srcpath, NULL, flags, drv); ++ ret = bdrv_open(bs, srcpath, NULL, flags, drv, &local_err); + if (ret < 0) { + errno = -ret; +- err(EXIT_FAILURE, "Failed to bdrv_open '%s'", argv[optind]); ++ err(EXIT_FAILURE, "Failed to bdrv_open '%s': %s", argv[optind], ++ error_get_pretty(local_err)); + } + + fd_size = bdrv_getlength(bs); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Fix-compiler-warning-Werror-uninitialized.patch b/SOURCES/kvm-block-Fix-compiler-warning-Werror-uninitialized.patch new file mode 100644 index 0000000..983909b --- /dev/null +++ b/SOURCES/kvm-block-Fix-compiler-warning-Werror-uninitialized.patch @@ -0,0 +1,72 @@ +From b888e19c99ff56e39a1e7364d66077a4dbfa512b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:34 +0200 +Subject: [PATCH 09/81] block: Fix compiler warning (-Werror=uninitialized) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-10-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54991 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 09/26] block: Fix compiler warning (-Werror=uninitialized) +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Stefan Weil + +The patch fixes a warning from gcc (Debian 4.6.3-14+rpi1) 4.6.3: + +block/stream.c:141:22: error: +‘copy’ may be used uninitialized in this function [-Werror=uninitialized] + +This is not a real bug - a better compiler would not complain. + +Now 'copy' has always a defined value, so the check for ret >= 0 +can be removed. + +Signed-off-by: Stefan Weil +Acked-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit c3e4f43a99549daa6e9b87350922e8339341c2ab) +--- + block/stream.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/stream.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/stream.c b/block/stream.c +index 995b97b..276487c 100644 +--- a/block/stream.c ++++ b/block/stream.c +@@ -115,11 +115,12 @@ wait: + break; + } + ++ copy = false; ++ + ret = bdrv_is_allocated(bs, sector_num, + STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n); + if (ret == 1) { + /* Allocated in the top, no need to copy. */ +- copy = false; + } else if (ret >= 0) { + /* Copy if allocated in the intermediate images. Limit to the + * known-unallocated area [sector_num, sector_num+n). */ +@@ -134,7 +135,7 @@ wait: + copy = (ret == 1); + } + trace_stream_one_iteration(s, sector_num, n, ret); +- if (ret >= 0 && copy) { ++ if (copy) { + if (s->common.speed) { + delay_ns = ratelimit_calculate_delay(&s->limit, n); + if (delay_ns > 0) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Introduce-bs-zero_beyond_eof.patch b/SOURCES/kvm-block-Introduce-bs-zero_beyond_eof.patch new file mode 100644 index 0000000..371ed89 --- /dev/null +++ b/SOURCES/kvm-block-Introduce-bs-zero_beyond_eof.patch @@ -0,0 +1,105 @@ +From 49b4262336e2875280d7d539851b5b318a86bc39 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Thu, 12 Sep 2013 07:39:33 +0200 +Subject: [PATCH 13/29] block: Introduce bs->zero_beyond_eof + +RH-Author: Asias He +Message-id: <1378971575-22416-3-git-send-email-asias@redhat.com> +Patchwork-id: 54326 +O-Subject: [RHEL7.0 qemu-kvm PATCH 2/4] block: Introduce bs->zero_beyond_eof +Bugzilla: 1007226 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1007226 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6275752 + +In 4146b46c42e0989cb5842e04d88ab6ccb1713a48 (block: Produce zeros when +protocols reading beyond end of file), we break qemu-iotests ./check +-qcow2 022. This happens because qcow2 temporarily sets ->growable = 1 +for vmstate accesses (which are stored beyond the end of regular image +data). + +We introduce the bs->zero_beyond_eof to allow qcow2_load_vmstate() to +disable ->zero_beyond_eof temporarily in addition to enable ->growable. + +[Since the broken patch "block: Produce zeros when protocols reading +beyond end of file" has not been merged yet, I have applied this fix +*first* and will then apply the next patch to keep the tree bisectable. +-- Stefan] + +Suggested-by: Stefan Hajnoczi +Signed-off-by: Asias He +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 0d51b4debee6fb322751a57097a1d675c7a7c38d) +--- + block.c | 2 ++ + block/qcow2.c | 3 +++ + include/block/block_int.h | 3 +++ + 3 files changed, 8 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 2 ++ + block/qcow2.c | 3 +++ + include/block/block_int.h | 3 +++ + 3 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/block.c b/block.c +index f4a89b9..dbcad0e 100644 +--- a/block.c ++++ b/block.c +@@ -708,6 +708,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + + bs->open_flags = flags; + bs->buffer_alignment = 512; ++ bs->zero_beyond_eof = true; + open_flags = bdrv_open_flags(bs, flags); + bs->read_only = !(open_flags & BDRV_O_RDWR); + +@@ -1407,6 +1408,7 @@ void bdrv_close(BlockDriverState *bs) + bs->valid_key = 0; + bs->sg = 0; + bs->growable = 0; ++ bs->zero_beyond_eof = false; + QDECREF(bs->options); + bs->options = NULL; + +diff --git a/block/qcow2.c b/block/qcow2.c +index abdc202..70da5bd 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1722,12 +1722,15 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, + { + BDRVQcowState *s = bs->opaque; + int growable = bs->growable; ++ bool zero_beyond_eof = bs->zero_beyond_eof; + int ret; + + BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD); + bs->growable = 1; ++ bs->zero_beyond_eof = false; + ret = bdrv_pread(bs, qcow2_vm_state_offset(s) + pos, buf, size); + bs->growable = growable; ++ bs->zero_beyond_eof = zero_beyond_eof; + + return ret; + } +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 6078dd3..267be48 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -268,6 +268,9 @@ struct BlockDriverState { + /* Whether the disk can expand beyond total_sectors */ + int growable; + ++ /* Whether produces zeros when read beyond eof */ ++ bool zero_beyond_eof; ++ + /* the memory alignment required for the buffers handled by this driver */ + int buffer_alignment; + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-Produce-zeros-when-protocols-reading-beyond-en.patch b/SOURCES/kvm-block-Produce-zeros-when-protocols-reading-beyond-en.patch new file mode 100644 index 0000000..f8ad289 --- /dev/null +++ b/SOURCES/kvm-block-Produce-zeros-when-protocols-reading-beyond-en.patch @@ -0,0 +1,106 @@ +From 12e88a4a74931578a5582b5caeca135fe85fb01b Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Thu, 12 Sep 2013 07:39:34 +0200 +Subject: [PATCH 14/29] block: Produce zeros when protocols reading beyond end of file + +RH-Author: Asias He +Message-id: <1378971575-22416-4-git-send-email-asias@redhat.com> +Patchwork-id: 54325 +O-Subject: [RHEL7.0 qemu-kvm PATCH 3/4] block: Produce zeros when protocols reading beyond end of file +Bugzilla: 1007226 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng + +From: MORITA Kazutaka + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1005052 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6275752 + +While Asias is debugging an issue creating qcow2 images on top of +non-file protocols. It boils down to this example using NBD: + +$ qemu-io -c 'open -g nbd+unix:///?socket=/tmp/nbd.sock' -c 'read -v 0 512' + +Notice the open -g option to set bs->growable. This means you can +read/write beyond end of file. Reading beyond end of file is supposed +to produce zeroes. + +We rely on this behavior in qcow2_create2() during qcow2 image +creation. We create a new file and then write the qcow2 header +structure using bdrv_pwrite(). Since QCowHeader is not a multiple of +sector size, block.c first uses bdrv_read() on the empty file to fetch +the first sector (should be all zeroes). + +Here is the output from the qemu-io NBD example above: + +$ qemu-io -c 'open -g nbd+unix:///?socket=/tmp/nbd.sock' -c 'read -v 0 512' +00000000: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ................ +00000010: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ................ +00000020: ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ................ +... + +We are not zeroing the buffer! As a result qcow2 image creation on top +of protocols is not guaranteed to work even when file creation is +supported by the protocol. + +[Adapted this patch to use bs->zero_beyond_eof. +-- Stefan] + +Signed-off-by: MORITA Kazutaka +Signed-off-by: Asias He +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 893a8f6220368a9ebff9a74bd48359928545cf6a) +--- + block.c | 30 +++++++++++++++++++++++++++++- + 1 file changed, 29 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 30 +++++++++++++++++++++++++++++- + 1 files changed, 29 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index dbcad0e..a3bc800 100644 +--- a/block.c ++++ b/block.c +@@ -2555,7 +2555,35 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, + } + } + +- ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); ++ if (!(bs->zero_beyond_eof && bs->growable)) { ++ ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov); ++ } else { ++ /* Read zeros after EOF of growable BDSes */ ++ int64_t len, total_sectors, max_nb_sectors; ++ ++ len = bdrv_getlength(bs); ++ if (len < 0) { ++ ret = len; ++ goto out; ++ } ++ ++ total_sectors = len >> BDRV_SECTOR_BITS; ++ max_nb_sectors = MAX(0, total_sectors - sector_num); ++ if (max_nb_sectors > 0) { ++ ret = drv->bdrv_co_readv(bs, sector_num, ++ MIN(nb_sectors, max_nb_sectors), qiov); ++ } else { ++ ret = 0; ++ } ++ ++ /* Reading beyond end of file is supposed to produce zeroes */ ++ if (ret == 0 && total_sectors < sector_num + nb_sectors) { ++ uint64_t offset = MAX(0, total_sectors - sector_num); ++ uint64_t bytes = (sector_num + nb_sectors - offset) * ++ BDRV_SECTOR_SIZE; ++ qemu_iovec_memset(qiov, offset * BDRV_SECTOR_SIZE, 0, bytes); ++ } ++ } + + out: + tracked_request_end(&req); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-add-bdrv_write_zeroes.patch b/SOURCES/kvm-block-add-bdrv_write_zeroes.patch new file mode 100644 index 0000000..039c001 --- /dev/null +++ b/SOURCES/kvm-block-add-bdrv_write_zeroes.patch @@ -0,0 +1,139 @@ +From f6f47020d06eca20a99967b6ac9eef65326dfdde Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:06 +0200 +Subject: [PATCH 11/25] block: add bdrv_write_zeroes() + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-2-git-send-email-owasserm@redhat.com> +Patchwork-id: 54797 +O-Subject: [RHEL7.0 qemu-kvm v2 01/10] block: add bdrv_write_zeroes() +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Peter Lieven + +Signed-off-by: Peter Lieven +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 4105eaaab9376ea959de711b81bba9e1494c971d) +--- + block.c | 27 +++++++++++++++++++-------- + include/block/block.h | 2 ++ + 2 files changed, 21 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 27 +++++++++++++++++++-------- + include/block/block.h | 2 ++ + 2 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/block.c b/block.c +index bd52c13..b160f62 100644 +--- a/block.c ++++ b/block.c +@@ -2190,6 +2190,7 @@ typedef struct RwCo { + QEMUIOVector *qiov; + bool is_write; + int ret; ++ BdrvRequestFlags flags; + } RwCo; + + static void coroutine_fn bdrv_rw_co_entry(void *opaque) +@@ -2198,10 +2199,12 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque) + + if (!rwco->is_write) { + rwco->ret = bdrv_co_do_readv(rwco->bs, rwco->sector_num, +- rwco->nb_sectors, rwco->qiov, 0); ++ rwco->nb_sectors, rwco->qiov, ++ rwco->flags); + } else { + rwco->ret = bdrv_co_do_writev(rwco->bs, rwco->sector_num, +- rwco->nb_sectors, rwco->qiov, 0); ++ rwco->nb_sectors, rwco->qiov, ++ rwco->flags); + } + } + +@@ -2209,7 +2212,8 @@ static void coroutine_fn bdrv_rw_co_entry(void *opaque) + * Process a vectored synchronous request using coroutines + */ + static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, +- QEMUIOVector *qiov, bool is_write) ++ QEMUIOVector *qiov, bool is_write, ++ BdrvRequestFlags flags) + { + Coroutine *co; + RwCo rwco = { +@@ -2219,6 +2223,7 @@ static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, + .qiov = qiov, + .is_write = is_write, + .ret = NOT_DONE, ++ .flags = flags, + }; + assert((qiov->size & (BDRV_SECTOR_SIZE - 1)) == 0); + +@@ -2250,7 +2255,7 @@ static int bdrv_rwv_co(BlockDriverState *bs, int64_t sector_num, + * Process a synchronous request using coroutines + */ + static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, +- int nb_sectors, bool is_write) ++ int nb_sectors, bool is_write, BdrvRequestFlags flags) + { + QEMUIOVector qiov; + struct iovec iov = { +@@ -2259,14 +2264,14 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, + }; + + qemu_iovec_init_external(&qiov, &iov, 1); +- return bdrv_rwv_co(bs, sector_num, &qiov, is_write); ++ return bdrv_rwv_co(bs, sector_num, &qiov, is_write, flags); + } + + /* return < 0 if error. See bdrv_write() for the return codes */ + int bdrv_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) + { +- return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false); ++ return bdrv_rw_co(bs, sector_num, buf, nb_sectors, false, 0); + } + + /* Just like bdrv_read(), but with I/O throttling temporarily disabled */ +@@ -2292,12 +2297,18 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, + int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) + { +- return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true); ++ return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true, 0); + } + + int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov) + { +- return bdrv_rwv_co(bs, sector_num, qiov, true); ++ return bdrv_rwv_co(bs, sector_num, qiov, true, 0); ++} ++ ++int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, int nb_sectors) ++{ ++ return bdrv_rw_co(bs, sector_num, NULL, nb_sectors, true, ++ BDRV_REQ_ZERO_WRITE); + } + + int bdrv_pread(BlockDriverState *bs, int64_t offset, +diff --git a/include/block/block.h b/include/block/block.h +index 174295b..1a3ed22 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -168,6 +168,8 @@ int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors); + int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); ++int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num, ++ int nb_sectors); + int bdrv_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov); + int bdrv_pread(BlockDriverState *bs, int64_t offset, + void *buf, int count); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-add-default-get_block_status-implementation-fo.patch b/SOURCES/kvm-block-add-default-get_block_status-implementation-fo.patch new file mode 100644 index 0000000..044c603 --- /dev/null +++ b/SOURCES/kvm-block-add-default-get_block_status-implementation-fo.patch @@ -0,0 +1,49 @@ +From 815d053228bffeb0c2774f283c249ddf7f5fb03e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:46 +0200 +Subject: [PATCH 21/81] block: add default get_block_status implementation for protocols + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-22-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55004 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 21/26] block: add default get_block_status implementation for protocols +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Protocols return raw data, so you can assume the offsets to pass +through unchanged. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 918e92d71b38306a6bf4fedfd1109367f1425587) +--- + block.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 36a2f24..2a4a9dd 100644 +--- a/block.c ++++ b/block.c +@@ -3060,7 +3060,11 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + + if (!bs->drv->bdrv_co_get_block_status) { + *pnum = nb_sectors; +- return BDRV_BLOCK_DATA; ++ ret = BDRV_BLOCK_DATA; ++ if (bs->drv->protocol_name) { ++ ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE); ++ } ++ return ret; + } + + ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-add-image-info-query-function-bdrv_query_image.patch b/SOURCES/kvm-block-add-image-info-query-function-bdrv_query_image.patch new file mode 100644 index 0000000..b8d9d8a --- /dev/null +++ b/SOURCES/kvm-block-add-image-info-query-function-bdrv_query_image.patch @@ -0,0 +1,165 @@ +From e705ed7009ed1d53dd1d382cb8cf61a562dc8a44 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:28 +0100 +Subject: [PATCH 71/87] block: add image info query function bdrv_query_image_info() + +RH-Author: Max Reitz +Message-id: <1383756824-6921-6-git-send-email-mreitz@redhat.com> +Patchwork-id: 55560 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 05/21] block: add image info query function bdrv_query_image_info() +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Wenchao Xia + +BZ: 980771 + +This patch adds function bdrv_query_image_info(), which will +retrieve image info in qmp object format. The implementation is +based on the code moved from qemu-img.c, but uses block layer +function to get snapshot info. + +Signed-off-by: Wenchao Xia +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 43526ec8d1395fe4efbed15e9764b64641b95bcc) + +Signed-off-by: Max Reitz +--- + block/qapi.c | 43 +++++++++++++++++++++++++++++++++++++------ + include/block/qapi.h | 6 +++--- + qemu-img.c | 11 ++++++----- + 3 files changed, 46 insertions(+), 14 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qapi.c | 43 +++++++++++++++++++++++++++++++++++++------ + include/block/qapi.h | 6 +++--- + qemu-img.c | 11 ++++++----- + 3 files changed, 46 insertions(+), 14 deletions(-) + +diff --git a/block/qapi.c b/block/qapi.c +index 1ed56da..e9d8b74 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -88,18 +88,29 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, + return 0; + } + +-void bdrv_collect_image_info(BlockDriverState *bs, +- ImageInfo *info, +- const char *filename) ++/** ++ * bdrv_query_image_info: ++ * @bs: block device to examine ++ * @p_info: location to store image information ++ * @errp: location to store error information ++ * ++ * @p_info will be set only on success. On error, store error in @errp. ++ */ ++void bdrv_query_image_info(BlockDriverState *bs, ++ ImageInfo **p_info, ++ Error **errp) + { + uint64_t total_sectors; +- char backing_filename[1024]; ++ const char *backing_filename; + char backing_filename2[1024]; + BlockDriverInfo bdi; ++ int ret; ++ Error *err = NULL; ++ ImageInfo *info = g_new0(ImageInfo, 1); + + bdrv_get_geometry(bs, &total_sectors); + +- info->filename = g_strdup(filename); ++ info->filename = g_strdup(bs->filename); + info->format = g_strdup(bdrv_get_format_name(bs)); + info->virtual_size = total_sectors * 512; + info->actual_size = bdrv_get_allocated_file_size(bs); +@@ -116,7 +127,7 @@ void bdrv_collect_image_info(BlockDriverState *bs, + info->dirty_flag = bdi.is_dirty; + info->has_dirty_flag = true; + } +- bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); ++ backing_filename = bs->backing_file; + if (backing_filename[0] != '\0') { + info->backing_filename = g_strdup(backing_filename); + info->has_backing_filename = true; +@@ -134,6 +145,26 @@ void bdrv_collect_image_info(BlockDriverState *bs, + info->has_backing_filename_format = true; + } + } ++ ++ ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err); ++ switch (ret) { ++ case 0: ++ if (info->snapshots) { ++ info->has_snapshots = true; ++ } ++ break; ++ /* recoverable error */ ++ case -ENOMEDIUM: ++ case -ENOTSUP: ++ error_free(err); ++ break; ++ default: ++ error_propagate(errp, err); ++ qapi_free_ImageInfo(info); ++ return; ++ } ++ ++ *p_info = info; + } + + BlockInfo *bdrv_query_info(BlockDriverState *bs) +diff --git a/include/block/qapi.h b/include/block/qapi.h +index 4f223d1..ab1f48f 100644 +--- a/include/block/qapi.h ++++ b/include/block/qapi.h +@@ -32,9 +32,9 @@ + int bdrv_query_snapshot_info_list(BlockDriverState *bs, + SnapshotInfoList **p_list, + Error **errp); +-void bdrv_collect_image_info(BlockDriverState *bs, +- ImageInfo *info, +- const char *filename); ++void bdrv_query_image_info(BlockDriverState *bs, ++ ImageInfo **p_info, ++ Error **errp); + BlockInfo *bdrv_query_info(BlockDriverState *s); + BlockStats *bdrv_query_stats(const BlockDriverState *bs); + +diff --git a/qemu-img.c b/qemu-img.c +index e1fb148..fa0fd0e 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1663,6 +1663,7 @@ static ImageInfoList *collect_image_info_list(const char *filename, + ImageInfoList *head = NULL; + ImageInfoList **last = &head; + GHashTable *filenames; ++ Error *err = NULL; + + filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL); + +@@ -1684,11 +1685,11 @@ static ImageInfoList *collect_image_info_list(const char *filename, + goto err; + } + +- info = g_new0(ImageInfo, 1); +- bdrv_collect_image_info(bs, info, filename); +- bdrv_query_snapshot_info_list(bs, &info->snapshots, NULL); +- if (info->snapshots) { +- info->has_snapshots = true; ++ bdrv_query_image_info(bs, &info, &err); ++ if (error_is_set(&err)) { ++ error_report("%s", error_get_pretty(err)); ++ error_free(err); ++ goto err; + } + + elem = g_new0(ImageInfoList, 1); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-add-snapshot-info-query-function-bdrv_query_sn.patch b/SOURCES/kvm-block-add-snapshot-info-query-function-bdrv_query_sn.patch new file mode 100644 index 0000000..39e0370 --- /dev/null +++ b/SOURCES/kvm-block-add-snapshot-info-query-function-bdrv_query_sn.patch @@ -0,0 +1,159 @@ +From c4aaafbe296b0e38a54191d294436ffd718a2c7b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:27 +0100 +Subject: [PATCH 70/87] block: add snapshot info query function bdrv_query_snapshot_info_list() + +RH-Author: Max Reitz +Message-id: <1383756824-6921-5-git-send-email-mreitz@redhat.com> +Patchwork-id: 55559 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 04/21] block: add snapshot info query function bdrv_query_snapshot_info_list() +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Wenchao Xia + +BZ: 980771 + +This patch adds function bdrv_query_snapshot_info_list(), which will +retrieve snapshot info of an image in qmp object format. The implementation +is based on the code moved from qemu-img.c with modification to fit more +for qmp based block layer API. + +Signed-off-by: Wenchao Xia +Reviewed-by: Eric Blake +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit fb0ed4539c6f02fa9e5a3cf9df2549713451eeca) + +Signed-off-by: Max Reitz +--- + block/qapi.c | 55 +++++++++++++++++++++++++++++++++++++++------------- + include/block/qapi.h | 4 +++- + qemu-img.c | 5 ++++- + 3 files changed, 49 insertions(+), 15 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qapi.c | 55 ++++++++++++++++++++++++++++++++++++++----------- + include/block/qapi.h | 4 ++- + qemu-img.c | 5 +++- + 3 files changed, 49 insertions(+), 15 deletions(-) + +diff --git a/block/qapi.c b/block/qapi.c +index 794dbf8..1ed56da 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -26,29 +26,56 @@ + #include "block/block_int.h" + #include "qmp-commands.h" + +-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info) ++/* ++ * Returns 0 on success, with *p_list either set to describe snapshot ++ * information, or NULL because there are no snapshots. Returns -errno on ++ * error, with *p_list untouched. ++ */ ++int bdrv_query_snapshot_info_list(BlockDriverState *bs, ++ SnapshotInfoList **p_list, ++ Error **errp) + { + int i, sn_count; + QEMUSnapshotInfo *sn_tab = NULL; +- SnapshotInfoList *info_list, *cur_item = NULL; ++ SnapshotInfoList *info_list, *cur_item = NULL, *head = NULL; ++ SnapshotInfo *info; ++ + sn_count = bdrv_snapshot_list(bs, &sn_tab); ++ if (sn_count < 0) { ++ const char *dev = bdrv_get_device_name(bs); ++ switch (sn_count) { ++ case -ENOMEDIUM: ++ error_setg(errp, "Device '%s' is not inserted", dev); ++ break; ++ case -ENOTSUP: ++ error_setg(errp, ++ "Device '%s' does not support internal snapshots", ++ dev); ++ break; ++ default: ++ error_setg_errno(errp, -sn_count, ++ "Can't list snapshots of device '%s'", dev); ++ break; ++ } ++ return sn_count; ++ } + + for (i = 0; i < sn_count; i++) { +- info->has_snapshots = true; +- info_list = g_new0(SnapshotInfoList, 1); ++ info = g_new0(SnapshotInfo, 1); ++ info->id = g_strdup(sn_tab[i].id_str); ++ info->name = g_strdup(sn_tab[i].name); ++ info->vm_state_size = sn_tab[i].vm_state_size; ++ info->date_sec = sn_tab[i].date_sec; ++ info->date_nsec = sn_tab[i].date_nsec; ++ info->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; ++ info->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; + +- info_list->value = g_new0(SnapshotInfo, 1); +- info_list->value->id = g_strdup(sn_tab[i].id_str); +- info_list->value->name = g_strdup(sn_tab[i].name); +- info_list->value->vm_state_size = sn_tab[i].vm_state_size; +- info_list->value->date_sec = sn_tab[i].date_sec; +- info_list->value->date_nsec = sn_tab[i].date_nsec; +- info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; +- info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; ++ info_list = g_new0(SnapshotInfoList, 1); ++ info_list->value = info; + + /* XXX: waiting for the qapi to support qemu-queue.h types */ + if (!cur_item) { +- info->snapshots = cur_item = info_list; ++ head = cur_item = info_list; + } else { + cur_item->next = info_list; + cur_item = info_list; +@@ -57,6 +84,8 @@ void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info) + } + + g_free(sn_tab); ++ *p_list = head; ++ return 0; + } + + void bdrv_collect_image_info(BlockDriverState *bs, +diff --git a/include/block/qapi.h b/include/block/qapi.h +index e6e568d..4f223d1 100644 +--- a/include/block/qapi.h ++++ b/include/block/qapi.h +@@ -29,7 +29,9 @@ + #include "block/block.h" + #include "block/snapshot.h" + +-void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info); ++int bdrv_query_snapshot_info_list(BlockDriverState *bs, ++ SnapshotInfoList **p_list, ++ Error **errp); + void bdrv_collect_image_info(BlockDriverState *bs, + ImageInfo *info, + const char *filename); +diff --git a/qemu-img.c b/qemu-img.c +index 97b4212..e1fb148 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1686,7 +1686,10 @@ static ImageInfoList *collect_image_info_list(const char *filename, + + info = g_new0(ImageInfo, 1); + bdrv_collect_image_info(bs, info, filename); +- bdrv_collect_snapshots(bs, info); ++ bdrv_query_snapshot_info_list(bs, &info->snapshots, NULL); ++ if (info->snapshots) { ++ info->has_snapshots = true; ++ } + + elem = g_new0(ImageInfoList, 1); + elem->value = info; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-bdrv_reopen_prepare-don-t-use-QERR_OPEN_FILE_F.patch b/SOURCES/kvm-block-bdrv_reopen_prepare-don-t-use-QERR_OPEN_FILE_F.patch new file mode 100644 index 0000000..4bc6c88 --- /dev/null +++ b/SOURCES/kvm-block-bdrv_reopen_prepare-don-t-use-QERR_OPEN_FILE_F.patch @@ -0,0 +1,54 @@ +From a2ffa303cf6f0669c3810200211b4362ce2ac55e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:30 +0100 +Subject: [PATCH 11/29] block: bdrv_reopen_prepare(): don't use QERR_OPEN_FILE_FAILED + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-8-git-send-email-lersek@redhat.com> +Patchwork-id: 55197 +O-Subject: [RHEL-7 qemu-kvm PATCH 7/8] block: bdrv_reopen_prepare(): don't use QERR_OPEN_FILE_FAILED +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +The call to drv->bdrv_reopen_prepare() can fail due to reasons +other than an open failure. Unfortunately, we can't use errno +nor -ret, cause they are not always set. + +Stick to a generic error message then. + +Signed-off-by: Luiz Capitulino +Reviewed-by: Stefan Hajnoczi +Acked-by: Kevin Wolf +(cherry picked from commit d8b6895f7a8e5bcc5be1557e8048db43882f3b33) +Signed-off-by: Laszlo Ersek +--- + block.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index b160f62..2ba9a0a 100644 +--- a/block.c ++++ b/block.c +@@ -1309,8 +1309,8 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue, + if (local_err != NULL) { + error_propagate(errp, local_err); + } else { +- error_set(errp, QERR_OPEN_FILE_FAILED, +- reopen_state->bs->filename); ++ error_setg(errp, "failed while preparing to reopen image '%s'", ++ reopen_state->bs->filename); + } + goto error; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-define-get_block_status-return-value.patch b/SOURCES/kvm-block-define-get_block_status-return-value.patch new file mode 100644 index 0000000..feed64b --- /dev/null +++ b/SOURCES/kvm-block-define-get_block_status-return-value.patch @@ -0,0 +1,106 @@ +From 68c09ecc5cb4154d5d7ef839b3d20e7a4f45bc32 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:38 +0200 +Subject: [PATCH 13/81] block: define get_block_status return value + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-14-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54997 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 13/26] block: define get_block_status return value +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Define the return value of get_block_status. Bits 0, 1, 2 and 9-62 +are valid; bit 63 (the sign bit) is reserved for errors. Bits 3-8 +are left for future extensions. + +The return code is compatible with the old is_allocated API: if a driver +only returns 0 or 1 (aka BDRV_BLOCK_DATA) like is_allocated used to, +clients of is_allocated will not have any change in behavior. Still, +we will return more precise information in the next patches and the +new definition of bdrv_is_allocated is already prepared for this. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4333bb71405f58a8dc8d3255feb3ca5960b0daf8) +--- + block.c | 10 ++++++++-- + include/block/block.h | 26 ++++++++++++++++++++++++++ + 2 files changed, 34 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 10 ++++++++-- + include/block/block.h | 26 ++++++++++++++++++++++++++ + 2 files changed, 34 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index 772f5b7..8c583bf 100644 +--- a/block.c ++++ b/block.c +@@ -3059,7 +3059,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + + if (!bs->drv->bdrv_co_get_block_status) { + *pnum = nb_sectors; +- return 1; ++ return BDRV_BLOCK_DATA; + } + + return bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); +@@ -3109,7 +3109,13 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, + int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) + { +- return bdrv_get_block_status(bs, sector_num, nb_sectors, pnum); ++ int64_t ret = bdrv_get_block_status(bs, sector_num, nb_sectors, pnum); ++ if (ret < 0) { ++ return ret; ++ } ++ return ++ (ret & BDRV_BLOCK_DATA) || ++ ((ret & BDRV_BLOCK_ZERO) && !bdrv_has_zero_init(bs)); + } + + /* +diff --git a/include/block/block.h b/include/block/block.h +index a733f5f..01f5c65 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -92,6 +92,32 @@ typedef struct BlockDevOps { + #define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS) + #define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1) + ++/* BDRV_BLOCK_DATA: data is read from bs->file or another file ++ * BDRV_BLOCK_ZERO: sectors read as zero ++ * BDRV_BLOCK_OFFSET_VALID: sector stored in bs->file as raw data ++ * ++ * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 represent the offset in ++ * bs->file where sector data can be read from as raw data. ++ * ++ * DATA == 0 && ZERO == 0 means that data is read from backing_hd if present. ++ * ++ * DATA ZERO OFFSET_VALID ++ * t t t sectors read as zero, bs->file is zero at offset ++ * t f t sectors read as valid from bs->file at offset ++ * f t t sectors preallocated, read as zero, bs->file not ++ * necessarily zero at offset ++ * f f t sectors preallocated but read from backing_hd, ++ * bs->file contains garbage at offset ++ * t t f sectors preallocated, read as zero, unknown offset ++ * t f f sectors read from unknown file or offset ++ * f t f not allocated or unknown offset, read as zero ++ * f f f not allocated or unknown offset, read from backing_hd ++ */ ++#define BDRV_BLOCK_DATA 1 ++#define BDRV_BLOCK_ZERO 2 ++#define BDRV_BLOCK_OFFSET_VALID 4 ++#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK ++ + typedef enum { + BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP + } BlockErrorAction; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-do-not-use-total_sectors-in-bdrv_co_is_allocat.patch b/SOURCES/kvm-block-do-not-use-total_sectors-in-bdrv_co_is_allocat.patch new file mode 100644 index 0000000..f70f9f6 --- /dev/null +++ b/SOURCES/kvm-block-do-not-use-total_sectors-in-bdrv_co_is_allocat.patch @@ -0,0 +1,51 @@ +From 0dbbdb969ae54cf3042ec60f740e9c4773726013 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:31 +0200 +Subject: [PATCH 06/81] block: do not use ->total_sectors in bdrv_co_is_allocated + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-7-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54989 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 06/26] block: do not use ->total_sectors in bdrv_co_is_allocated +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +This is more robust when the device has removable media. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 617ccb466e1937a5c99332ce77a47ebd29861ae4) +--- + block.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 0607cc6..9ea8221 100644 +--- a/block.c ++++ b/block.c +@@ -3031,9 +3031,15 @@ static int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { ++ int64_t length; + int64_t n; + +- if (sector_num >= bs->total_sectors) { ++ length = bdrv_getlength(bs); ++ if (length < 0) { ++ return length; ++ } ++ ++ if (sector_num >= (length >> BDRV_SECTOR_BITS)) { + *pnum = 0; + return 0; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-don-t-lose-data-from-last-incomplete-sector.patch b/SOURCES/kvm-block-don-t-lose-data-from-last-incomplete-sector.patch new file mode 100644 index 0000000..bb2353a --- /dev/null +++ b/SOURCES/kvm-block-don-t-lose-data-from-last-incomplete-sector.patch @@ -0,0 +1,48 @@ +From f0623f334b23dc9334ac9d227cc467c266b8b2c6 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Wed, 9 Oct 2013 09:50:21 +0200 +Subject: [PATCH 09/11] block: don't lose data from last incomplete sector + +RH-Author: Fam Zheng +Message-id: <1381312223-7074-2-git-send-email-famz@redhat.com> +Patchwork-id: 54793 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/3] block: don't lose data from last incomplete sector +Bugzilla: 1017049 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina + +To read the last sector that is not aligned to sector boundary, current +code for growable backends, since commit 893a8f6 "block: Produce zeros +when protocols reading beyond end of file", drops the data and directly +returns zeroes. That is incorrect. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit bcb9d66e8590151967e1dbe3724eec7ec71392e0) +Signed-off-by: Fam Zheng +--- + block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index a3bc800..bd52c13 100644 +--- a/block.c ++++ b/block.c +@@ -2567,7 +2567,7 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, + goto out; + } + +- total_sectors = len >> BDRV_SECTOR_BITS; ++ total_sectors = (len + BDRV_SECTOR_SIZE - 1) >> BDRV_SECTOR_BITS; + max_nb_sectors = MAX(0, total_sectors - sector_num); + if (max_nb_sectors > 0) { + ret = drv->bdrv_co_readv(bs, sector_num, +-- +1.7.1 + diff --git a/SOURCES/kvm-block-drop-bs_snapshots-global-variable.patch b/SOURCES/kvm-block-drop-bs_snapshots-global-variable.patch new file mode 100644 index 0000000..10052d6 --- /dev/null +++ b/SOURCES/kvm-block-drop-bs_snapshots-global-variable.patch @@ -0,0 +1,195 @@ +From bff9b33a3c4e0757c1e779ebedbffa391d926ecb Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:52 +0100 +Subject: [PATCH 01/87] block: drop bs_snapshots global variable + +RH-Author: Max Reitz +Message-id: <1383604354-12743-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 55301 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 01/43] block: drop bs_snapshots global variable +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Stefan Hajnoczi + +BZ: 1026524 + +The bs_snapshots global variable points to the BlockDriverState which +will be used to save vmstate. This is really a savevm.c concept but was +moved into block.c:bdrv_snapshots() when it became clear that hotplug +could result in a dangling pointer. + +While auditing the block layer's global state I came upon bs_snapshots +and realized that a variable is not necessary here. Simply find the +first BlockDriverState capable of internal snapshots each time this is +needed. + +The behavior of bdrv_snapshots() is preserved across hotplug because new +drives are always appended to the bdrv_states list. This means that +calling the new find_vmstate_bs() function is idempotent - it returns +the same BlockDriverState unless it was hot-unplugged. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Reviewed-by: Wenchao Xia +Signed-off-by: Wenchao Xia +Signed-off-by: Kevin Wolf +(cherry picked from commit 29d782710f87f01991bfc85cd9bef7d15280a5e2) + +Signed-off-by: Max Reitz +--- + block.c | 28 ---------------------------- + include/block/block.h | 1 - + savevm.c | 19 +++++++++++++++---- + 3 files changed, 15 insertions(+), 33 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 28 ---------------------------- + include/block/block.h | 1 - + savevm.c | 19 +++++++++++++++---- + 3 files changed, 15 insertions(+), 33 deletions(-) + +diff --git a/block.c b/block.c +index fdff92f..84a3a8d 100644 +--- a/block.c ++++ b/block.c +@@ -99,9 +99,6 @@ static QTAILQ_HEAD(, BlockDriverState) bdrv_states = + static QLIST_HEAD(, BlockDriver) bdrv_drivers = + QLIST_HEAD_INITIALIZER(bdrv_drivers); + +-/* The device to use for VM snapshots */ +-static BlockDriverState *bs_snapshots; +- + /* If non-zero, use only whitelisted block drivers */ + static int use_bdrv_whitelist; + +@@ -1384,9 +1381,6 @@ void bdrv_close(BlockDriverState *bs) + notifier_list_notify(&bs->close_notifiers, bs); + + if (bs->drv) { +- if (bs == bs_snapshots) { +- bs_snapshots = NULL; +- } + if (bs->backing_hd) { + bdrv_delete(bs->backing_hd); + bs->backing_hd = NULL; +@@ -1619,7 +1613,6 @@ void bdrv_delete(BlockDriverState *bs) + + bdrv_close(bs); + +- assert(bs != bs_snapshots); + g_free(bs); + } + +@@ -1663,9 +1656,6 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops, + { + bs->dev_ops = ops; + bs->dev_opaque = opaque; +- if (bdrv_dev_has_removable_media(bs) && bs == bs_snapshots) { +- bs_snapshots = NULL; +- } + } + + void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv, +@@ -3493,24 +3483,6 @@ int bdrv_is_snapshot(BlockDriverState *bs) + return !!(bs->open_flags & BDRV_O_SNAPSHOT); + } + +-BlockDriverState *bdrv_snapshots(void) +-{ +- BlockDriverState *bs; +- +- if (bs_snapshots) { +- return bs_snapshots; +- } +- +- bs = NULL; +- while ((bs = bdrv_next(bs))) { +- if (bdrv_can_snapshot(bs)) { +- bs_snapshots = bs; +- return bs; +- } +- } +- return NULL; +-} +- + int bdrv_snapshot_create(BlockDriverState *bs, + QEMUSnapshotInfo *sn_info) + { +diff --git a/include/block/block.h b/include/block/block.h +index bc1f5f6..3b3f40e 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -362,7 +362,6 @@ BlockInfo *bdrv_query_info(BlockDriverState *s); + BlockStats *bdrv_query_stats(const BlockDriverState *bs); + int bdrv_can_snapshot(BlockDriverState *bs); + int bdrv_is_snapshot(BlockDriverState *bs); +-BlockDriverState *bdrv_snapshots(void); + int bdrv_snapshot_create(BlockDriverState *bs, + QEMUSnapshotInfo *sn_info); + int bdrv_snapshot_goto(BlockDriverState *bs, +diff --git a/savevm.c b/savevm.c +index 1ed7f05..d9f3787 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -2262,6 +2262,17 @@ out: + return ret; + } + ++static BlockDriverState *find_vmstate_bs(void) ++{ ++ BlockDriverState *bs = NULL; ++ while ((bs = bdrv_next(bs))) { ++ if (bdrv_can_snapshot(bs)) { ++ return bs; ++ } ++ } ++ return NULL; ++} ++ + static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, + const char *name) + { +@@ -2338,7 +2349,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) + } + } + +- bs = bdrv_snapshots(); ++ bs = find_vmstate_bs(); + if (!bs) { + monitor_printf(mon, "No block device can accept snapshots\n"); + return; +@@ -2440,7 +2451,7 @@ int load_vmstate(const char *name) + QEMUFile *f; + int ret; + +- bs_vm_state = bdrv_snapshots(); ++ bs_vm_state = find_vmstate_bs(); + if (!bs_vm_state) { + error_report("No block device supports snapshots"); + return -ENOTSUP; +@@ -2519,7 +2530,7 @@ void do_delvm(Monitor *mon, const QDict *qdict) + int ret; + const char *name = qdict_get_str(qdict, "name"); + +- bs = bdrv_snapshots(); ++ bs = find_vmstate_bs(); + if (!bs) { + monitor_printf(mon, "No block device supports snapshots\n"); + return; +@@ -2551,7 +2562,7 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict) + int *available_snapshots; + char buf[256]; + +- bs = bdrv_snapshots(); ++ bs = find_vmstate_bs(); + if (!bs) { + monitor_printf(mon, "No available block device supports snapshots\n"); + return; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-dump-snapshot-and-image-info-to-specified-outp.patch b/SOURCES/kvm-block-dump-snapshot-and-image-info-to-specified-outp.patch new file mode 100644 index 0000000..76662c9 --- /dev/null +++ b/SOURCES/kvm-block-dump-snapshot-and-image-info-to-specified-outp.patch @@ -0,0 +1,251 @@ +From 427c29cd043ba19a46096c66fafb321aecb8bc9b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:26 +0100 +Subject: [PATCH 69/87] block: dump snapshot and image info to specified output + +RH-Author: Max Reitz +Message-id: <1383756824-6921-4-git-send-email-mreitz@redhat.com> +Patchwork-id: 55558 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 03/21] block: dump snapshot and image info to specified output +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Wenchao Xia + +BZ: 980771 + +bdrv_snapshot_dump() and bdrv_image_info_dump() do not dump to a buffer now, +some internal buffers are still used for format control, which have no +chance to be truncated. As a result, these two functions have no more issue +of truncation, and they can be used by both qemu and qemu-img with correct +parameter specified. + +Signed-off-by: Wenchao Xia +Signed-off-by: Kevin Wolf +(cherry picked from commit 5b91704469c0f801e0219f26458356872c4145ab) + +Signed-off-by: Max Reitz +--- + block/qapi.c | 66 ++++++++++++++++++++++++++++------------------------ + include/block/qapi.h | 6 +++-- + qemu-img.c | 9 +++---- + savevm.c | 7 +++--- + 4 files changed, 49 insertions(+), 39 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qapi.c | 66 +++++++++++++++++++++++++++---------------------- + include/block/qapi.h | 6 +++- + qemu-img.c | 9 ++++--- + savevm.c | 7 +++-- + 4 files changed, 49 insertions(+), 39 deletions(-) + +diff --git a/block/qapi.c b/block/qapi.c +index 155e77e..794dbf8 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -259,7 +259,8 @@ static char *get_human_readable_size(char *buf, int buf_size, int64_t size) + return buf; + } + +-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) ++void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, ++ QEMUSnapshotInfo *sn) + { + char buf1[128], date_buf[128], clock_buf[128]; + struct tm tm; +@@ -267,9 +268,9 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) + int64_t secs; + + if (!sn) { +- snprintf(buf, buf_size, +- "%-10s%-20s%7s%20s%15s", +- "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); ++ func_fprintf(f, ++ "%-10s%-20s%7s%20s%15s", ++ "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); + } else { + ti = sn->date_sec; + localtime_r(&ti, &tm); +@@ -282,17 +283,18 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) + (int)((secs / 60) % 60), + (int)(secs % 60), + (int)((sn->vm_clock_nsec / 1000000) % 1000)); +- snprintf(buf, buf_size, +- "%-10s%-20s%7s%20s%15s", +- sn->id_str, sn->name, +- get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size), +- date_buf, +- clock_buf); ++ func_fprintf(f, ++ "%-10s%-20s%7s%20s%15s", ++ sn->id_str, sn->name, ++ get_human_readable_size(buf1, sizeof(buf1), ++ sn->vm_state_size), ++ date_buf, ++ clock_buf); + } +- return buf; + } + +-void bdrv_image_info_dump(ImageInfo *info) ++void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, ++ ImageInfo *info) + { + char size_buf[128], dsize_buf[128]; + if (!info->has_actual_size) { +@@ -302,43 +304,46 @@ void bdrv_image_info_dump(ImageInfo *info) + info->actual_size); + } + get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); +- printf("image: %s\n" +- "file format: %s\n" +- "virtual size: %s (%" PRId64 " bytes)\n" +- "disk size: %s\n", +- info->filename, info->format, size_buf, +- info->virtual_size, +- dsize_buf); ++ func_fprintf(f, ++ "image: %s\n" ++ "file format: %s\n" ++ "virtual size: %s (%" PRId64 " bytes)\n" ++ "disk size: %s\n", ++ info->filename, info->format, size_buf, ++ info->virtual_size, ++ dsize_buf); + + if (info->has_encrypted && info->encrypted) { +- printf("encrypted: yes\n"); ++ func_fprintf(f, "encrypted: yes\n"); + } + + if (info->has_cluster_size) { +- printf("cluster_size: %" PRId64 "\n", info->cluster_size); ++ func_fprintf(f, "cluster_size: %" PRId64 "\n", ++ info->cluster_size); + } + + if (info->has_dirty_flag && info->dirty_flag) { +- printf("cleanly shut down: no\n"); ++ func_fprintf(f, "cleanly shut down: no\n"); + } + + if (info->has_backing_filename) { +- printf("backing file: %s", info->backing_filename); ++ func_fprintf(f, "backing file: %s", info->backing_filename); + if (info->has_full_backing_filename) { +- printf(" (actual path: %s)", info->full_backing_filename); ++ func_fprintf(f, " (actual path: %s)", info->full_backing_filename); + } +- putchar('\n'); ++ func_fprintf(f, "\n"); + if (info->has_backing_filename_format) { +- printf("backing file format: %s\n", info->backing_filename_format); ++ func_fprintf(f, "backing file format: %s\n", ++ info->backing_filename_format); + } + } + + if (info->has_snapshots) { + SnapshotInfoList *elem; +- char buf[256]; + +- printf("Snapshot list:\n"); +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); ++ func_fprintf(f, "Snapshot list:\n"); ++ bdrv_snapshot_dump(func_fprintf, f, NULL); ++ func_fprintf(f, "\n"); + + /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but + * we convert to the block layer's native QEMUSnapshotInfo for now. +@@ -354,7 +359,8 @@ void bdrv_image_info_dump(ImageInfo *info) + + pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); + pstrcpy(sn.name, sizeof(sn.name), elem->value->name); +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn)); ++ bdrv_snapshot_dump(func_fprintf, f, &sn); ++ func_fprintf(f, "\n"); + } + } + } +diff --git a/include/block/qapi.h b/include/block/qapi.h +index 55d1848..e6e568d 100644 +--- a/include/block/qapi.h ++++ b/include/block/qapi.h +@@ -36,6 +36,8 @@ void bdrv_collect_image_info(BlockDriverState *bs, + BlockInfo *bdrv_query_info(BlockDriverState *s); + BlockStats *bdrv_query_stats(const BlockDriverState *bs); + +-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); +-void bdrv_image_info_dump(ImageInfo *info); ++void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, ++ QEMUSnapshotInfo *sn); ++void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, ++ ImageInfo *info); + #endif +diff --git a/qemu-img.c b/qemu-img.c +index 0bc084d..97b4212 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1575,16 +1575,17 @@ static void dump_snapshots(BlockDriverState *bs) + { + QEMUSnapshotInfo *sn_tab, *sn; + int nb_sns, i; +- char buf[256]; + + nb_sns = bdrv_snapshot_list(bs, &sn_tab); + if (nb_sns <= 0) + return; + printf("Snapshot list:\n"); +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); ++ bdrv_snapshot_dump(fprintf, stdout, NULL); ++ printf("\n"); + for(i = 0; i < nb_sns; i++) { + sn = &sn_tab[i]; +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn)); ++ bdrv_snapshot_dump(fprintf, stdout, sn); ++ printf("\n"); + } + g_free(sn_tab); + } +@@ -1634,7 +1635,7 @@ static void dump_human_image_info_list(ImageInfoList *list) + } + delim = true; + +- bdrv_image_info_dump(elem->value); ++ bdrv_image_info_dump(fprintf, stdout, elem->value); + } + } + +diff --git a/savevm.c b/savevm.c +index f126bff..4d12d92 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -2540,7 +2540,6 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict) + int nb_sns, i, ret, available; + int total; + int *available_snapshots; +- char buf[256]; + + bs = find_vmstate_bs(); + if (!bs) { +@@ -2583,10 +2582,12 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict) + } + + if (total > 0) { +- monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); ++ bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, NULL); ++ monitor_printf(mon, "\n"); + for (i = 0; i < total; i++) { + sn = &sn_tab[available_snapshots[i]]; +- monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn)); ++ bdrv_snapshot_dump((fprintf_function)monitor_printf, mon, sn); ++ monitor_printf(mon, "\n"); + } + } else { + monitor_printf(mon, "There is no suitable snapshot available\n"); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-expect-errors-from-bdrv_co_is_allocated.patch b/SOURCES/kvm-block-expect-errors-from-bdrv_co_is_allocated.patch new file mode 100644 index 0000000..ec76700 --- /dev/null +++ b/SOURCES/kvm-block-expect-errors-from-bdrv_co_is_allocated.patch @@ -0,0 +1,162 @@ +From ebd7d27935a5ec9d5c72403fc1cd60af2e450e7c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:33 +0200 +Subject: [PATCH 08/81] block: expect errors from bdrv_co_is_allocated + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-9-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54992 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 08/26] block: expect errors from bdrv_co_is_allocated +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Some bdrv_is_allocated callers do not expect errors, but the fallback +in qcow2.c might make other callers trip on assertion failures or +infinite loops. + +Fix the callers to always look for errors. + +Cc: qemu-stable@nongnu.org +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit d663640c04f2aab810915c556390211d75457704) +--- + block.c | 7 +++++-- + block/cow.c | 6 +++++- + block/qcow2.c | 4 +--- + block/stream.c | 2 +- + qemu-img.c | 16 ++++++++++++++-- + qemu-io.c | 4 ++++ + 6 files changed, 30 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 7 +++++-- + block/cow.c | 6 +++++- + block/qcow2.c | 4 +--- + block/stream.c | 2 +- + qemu-img.c | 16 ++++++++++++++-- + qemu-io.c | 4 ++++ + 6 files changed, 30 insertions(+), 9 deletions(-) + +diff --git a/block.c b/block.c +index 46d9420..d838a3c 100644 +--- a/block.c ++++ b/block.c +@@ -1815,8 +1815,11 @@ int bdrv_commit(BlockDriverState *bs) + buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE); + + for (sector = 0; sector < total_sectors; sector += n) { +- if (bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) { +- ++ ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n); ++ if (ret < 0) { ++ goto ro_cleanup; ++ } ++ if (ret) { + if (bdrv_read(bs, sector, buf, n) != 0) { + ret = -EIO; + goto ro_cleanup; +diff --git a/block/cow.c b/block/cow.c +index 21bceaa..5a33b46 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -212,7 +212,11 @@ static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num, + int ret, n; + + while (nb_sectors > 0) { +- if (cow_co_is_allocated(bs, sector_num, nb_sectors, &n)) { ++ ret = cow_co_is_allocated(bs, sector_num, nb_sectors, &n); ++ if (ret < 0) { ++ return ret; ++ } ++ if (ret) { + ret = bdrv_pread(bs->file, + s->cow_sectors_offset + sector_num * 512, + buf, n * 512); +diff --git a/block/qcow2.c b/block/qcow2.c +index 70da5bd..f6e64d2 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -648,13 +648,11 @@ static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs, + int ret; + + *pnum = nb_sectors; +- /* FIXME We can get errors here, but the bdrv_co_is_allocated interface +- * can't pass them on today */ + qemu_co_mutex_lock(&s->lock); + ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset); + qemu_co_mutex_unlock(&s->lock); + if (ret < 0) { +- *pnum = 0; ++ return ret; + } + + return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO); +diff --git a/block/stream.c b/block/stream.c +index 9674c31..995b97b 100644 +--- a/block/stream.c ++++ b/block/stream.c +@@ -120,7 +120,7 @@ wait: + if (ret == 1) { + /* Allocated in the top, no need to copy. */ + copy = false; +- } else { ++ } else if (ret >= 0) { + /* Copy if allocated in the intermediate images. Limit to the + * known-unallocated area [sector_num, sector_num+n). */ + ret = bdrv_is_allocated_above(bs->backing_hd, base, +diff --git a/qemu-img.c b/qemu-img.c +index 3b11414..28efb4f 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1482,8 +1482,15 @@ static int img_convert(int argc, char **argv) + are present in both the output's and input's base images (no + need to copy them). */ + if (out_baseimg) { +- if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, +- n, &n1)) { ++ ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, ++ n, &n1); ++ if (ret < 0) { ++ error_report("error while reading metadata for sector " ++ "%" PRId64 ": %s", ++ sector_num - bs_offset, strerror(-ret)); ++ goto out; ++ } ++ if (!ret) { + sector_num += n1; + continue; + } +@@ -2217,6 +2224,11 @@ static int img_rebase(int argc, char **argv) + + /* If the cluster is allocated, we don't need to take action */ + ret = bdrv_is_allocated(bs, sector, n, &n); ++ if (ret < 0) { ++ error_report("error while reading image metadata: %s", ++ strerror(-ret)); ++ goto out; ++ } + if (ret) { + continue; + } +diff --git a/qemu-io.c b/qemu-io.c +index 5045ff8..bdcce7f 100644 +--- a/qemu-io.c ++++ b/qemu-io.c +@@ -1607,6 +1607,10 @@ static int alloc_f(int argc, char **argv) + sector_num = offset >> 9; + while (remaining) { + ret = bdrv_is_allocated(bs, sector_num, remaining, &num); ++ if (ret < 0) { ++ printf("is_allocated failed: %s\n", strerror(-ret)); ++ return 0; ++ } + sector_num += num; + remaining -= num; + if (ret) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-fix-backing-file-overriding.patch b/SOURCES/kvm-block-fix-backing-file-overriding.patch new file mode 100644 index 0000000..9fd2d2e --- /dev/null +++ b/SOURCES/kvm-block-fix-backing-file-overriding.patch @@ -0,0 +1,85 @@ +From f50d8d218780ea455bb7dc6d7ccdd0c5b931f4a8 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:17 +0100 +Subject: [PATCH 64/87] block: fix backing file overriding + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-24-git-send-email-kwolf@redhat.com> +Patchwork-id: 55402 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 23/24] block: fix backing file overriding +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +From: Fam Zheng + +Providing backing.file.filename doesn't override backing file as expected: + + $ x86_64-softmmu/qemu-system-x86_64 -drive \ + file=/tmp/child.qcow2,backing.file.filename=/tmp/fake.qcow2 + + qemu-system-x86_64: -drive \ + file=/tmp/child.qcow2,backing.file.filename=/tmp/fake.qcow2: could not + open disk image /tmp/child.qcow2: Can't specify 'file' and 'filename' + options at the same time + +With + + $ qemu-img info /tmp/child.qcow2 + image: /tmp/child.qcow2 + file format: qcow2 + virtual size: 1.0G (1073741824 bytes) + disk size: 196K + cluster_size: 65536 + backing file: /tmp/fake.qcow2 + +This fixes it by calling bdrv_get_full_backing_filename only if +backing.file.filename is not provided. Also save the backing file name +to bs->backing_file so the information is correct with HMP "info block". + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit dbecebddfa4932d1c83915bcb9b5ba5984eb91be) + +Signed-off-by: Kevin Wolf +--- + block.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index d11661a..01c11ee 100644 +--- a/block.c ++++ b/block.c +@@ -956,11 +956,12 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp) + } else if (bs->backing_file[0] == '\0' && qdict_size(options) == 0) { + QDECREF(options); + return 0; ++ } else { ++ bdrv_get_full_backing_filename(bs, backing_filename, ++ sizeof(backing_filename)); + } + + bs->backing_hd = bdrv_new(""); +- bdrv_get_full_backing_filename(bs, backing_filename, +- sizeof(backing_filename)); + + if (bs->backing_format[0] != '\0') { + back_drv = bdrv_find_format(bs->backing_format); +@@ -972,6 +973,8 @@ 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); ++ pstrcpy(bs->backing_file, sizeof(bs->backing_file), ++ bs->backing_hd->file->filename); + if (ret < 0) { + bdrv_delete(bs->backing_hd); + bs->backing_hd = NULL; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-fix-vvfat-error-path-for-enable_write_target.patch b/SOURCES/kvm-block-fix-vvfat-error-path-for-enable_write_target.patch new file mode 100644 index 0000000..68763e3 --- /dev/null +++ b/SOURCES/kvm-block-fix-vvfat-error-path-for-enable_write_target.patch @@ -0,0 +1,104 @@ +From 631c132d062d057d4648c88e5dfa4b8a375d3442 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:56 +0100 +Subject: [PATCH 03/87] block: fix vvfat error path for enable_write_target + +RH-Author: Max Reitz +Message-id: <1383604354-12743-6-git-send-email-mreitz@redhat.com> +Patchwork-id: 55305 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 05/43] block: fix vvfat error path for enable_write_target +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +BZ: 1026524 + +s->qcow and s->qcow_filename are allocated but not freed on error. Fix the +possible leaks, remove unnecessary check for bdrv_new(), propagate ret code of +bdrv_create() and also the one of enable_write_target(). + +Signed-off-by: Fam Zheng +Reviewed-by: Laszlo Ersek +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 78f27bd02ceba4a2f6ac5c725f4d4410eec205ef) + +Signed-off-by: Max Reitz +--- + block/vvfat.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/vvfat.c | 25 ++++++++++++++----------- + 1 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/block/vvfat.c b/block/vvfat.c +index 415fba3..dd0efca 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -1164,8 +1164,8 @@ DLOG(if (stderr == NULL) { + s->sector_count = cyls * heads * secs - (s->first_sectors_number - 1); + + if (qemu_opt_get_bool(opts, "rw", false)) { +- if (enable_write_target(s)) { +- ret = -EIO; ++ ret = enable_write_target(s); ++ if (ret < 0) { + goto fail; + } + bs->read_only = 0; +@@ -2918,9 +2918,7 @@ static int enable_write_target(BDRVVVFATState *s) + s->qcow_filename = g_malloc(1024); + ret = get_tmp_filename(s->qcow_filename, 1024); + if (ret < 0) { +- g_free(s->qcow_filename); +- s->qcow_filename = NULL; +- return ret; ++ goto err; + } + + bdrv_qcow = bdrv_find_format("qcow"); +@@ -2928,18 +2926,18 @@ static int enable_write_target(BDRVVVFATState *s) + set_option_parameter_int(options, BLOCK_OPT_SIZE, s->sector_count * 512); + set_option_parameter(options, BLOCK_OPT_BACKING_FILE, "fat:"); + +- if (bdrv_create(bdrv_qcow, s->qcow_filename, options) < 0) +- return -1; ++ ret = bdrv_create(bdrv_qcow, s->qcow_filename, options); ++ if (ret < 0) { ++ goto err; ++ } + + s->qcow = bdrv_new(""); +- if (s->qcow == NULL) { +- return -1; +- } + + ret = bdrv_open(s->qcow, s->qcow_filename, NULL, + BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, bdrv_qcow); + if (ret < 0) { +- return ret; ++ bdrv_delete(s->qcow); ++ goto err; + } + + #ifndef _WIN32 +@@ -2952,6 +2950,11 @@ static int enable_write_target(BDRVVVFATState *s) + *(void**)s->bs->backing_hd->opaque = s; + + return 0; ++ ++err: ++ g_free(s->qcow_filename); ++ s->qcow_filename = NULL; ++ return ret; + } + + static void vvfat_close(BlockDriverState *bs) +-- +1.7.1 + diff --git a/SOURCES/kvm-block-get_block_status-avoid-redundant-callouts-on-r.patch b/SOURCES/kvm-block-get_block_status-avoid-redundant-callouts-on-r.patch new file mode 100644 index 0000000..2164862 --- /dev/null +++ b/SOURCES/kvm-block-get_block_status-avoid-redundant-callouts-on-r.patch @@ -0,0 +1,92 @@ +From 69813093427b02a4a0e02264abd1f851f2b49249 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 7 Nov 2013 07:23:45 +0100 +Subject: [PATCH 26/81] block/get_block_status: avoid redundant callouts on raw devices + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-27-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55009 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 26/26] block/get_block_status: avoid redundant callouts on raw devices +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Peter Lieven + +if a raw device like an iscsi target or host device is used +the current implementation makes a second call out to get +the block status of bs->file. + +Signed-off-by: Peter Lieven +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 92bc50a5ad7fbc9a0bd17240eaea5027a100ca79) + +Conflicts: + block/raw_bsd.c + +Signed-off-by: Miroslav Rezanina +--- + block.c | 6 ++++++ + block/raw.c | 4 +++- + include/block/block.h | 4 ++++ + 3 files changed, 13 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 5c49461..fdff92f 100644 +--- a/block.c ++++ b/block.c +@@ -3073,6 +3073,12 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + return ret; + } + ++ if (ret & BDRV_BLOCK_RAW) { ++ assert(ret & BDRV_BLOCK_OFFSET_VALID); ++ return bdrv_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS, ++ *pnum, pnum); ++ } ++ + if (!(ret & BDRV_BLOCK_DATA)) { + if (bdrv_has_zero_init(bs)) { + ret |= BDRV_BLOCK_ZERO; +diff --git a/block/raw.c b/block/raw.c +index 844a222..7d82cf3 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -39,7 +39,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { +- return bdrv_get_block_status(bs->file, sector_num, nb_sectors, pnum); ++ *pnum = nb_sectors; ++ return BDRV_BLOCK_RAW | BDRV_BLOCK_OFFSET_VALID | BDRV_BLOCK_DATA | ++ (sector_num << BDRV_SECTOR_BITS); + } + + static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, +diff --git a/include/block/block.h b/include/block/block.h +index 01f5c65..bc1f5f6 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -95,6 +95,9 @@ typedef struct BlockDevOps { + /* BDRV_BLOCK_DATA: data is read from bs->file or another file + * BDRV_BLOCK_ZERO: sectors read as zero + * BDRV_BLOCK_OFFSET_VALID: sector stored in bs->file as raw data ++ * BDRV_BLOCK_RAW: used internally to indicate that the request ++ * was answered by the raw driver and that one ++ * should look in bs->file directly. + * + * If BDRV_BLOCK_OFFSET_VALID is set, bits 9-62 represent the offset in + * bs->file where sector data can be read from as raw data. +@@ -116,6 +119,7 @@ typedef struct BlockDevOps { + #define BDRV_BLOCK_DATA 1 + #define BDRV_BLOCK_ZERO 2 + #define BDRV_BLOCK_OFFSET_VALID 4 ++#define BDRV_BLOCK_RAW 8 + #define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK + + typedef enum { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-get_block_status-avoid-segfault-if-there-is-no.patch b/SOURCES/kvm-block-get_block_status-avoid-segfault-if-there-is-no.patch new file mode 100644 index 0000000..d31a299 --- /dev/null +++ b/SOURCES/kvm-block-get_block_status-avoid-segfault-if-there-is-no.patch @@ -0,0 +1,45 @@ +From cb57c159b8ffe151ce61750507c635d1d05e51b5 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:50 +0200 +Subject: [PATCH 25/81] block/get_block_status: avoid segfault if there is no backing_hd + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-26-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55008 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 25/26] block/get_block_status: avoid segfault if there is no backing_hd +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Peter Lieven + +Reviewed-by: Eric Blake +Signed-off-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit 1f9db2243c1b987c834fe559a8e73b3178f50c2b) +--- + block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 02e111e..5c49461 100644 +--- a/block.c ++++ b/block.c +@@ -3076,7 +3076,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + if (!(ret & BDRV_BLOCK_DATA)) { + if (bdrv_has_zero_init(bs)) { + ret |= BDRV_BLOCK_ZERO; +- } else { ++ } else if (bs->backing_hd) { + BlockDriverState *bs2 = bs->backing_hd; + int64_t length2 = bdrv_getlength(bs2); + if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-get_block_status-set-pnum-0-on-error.patch b/SOURCES/kvm-block-get_block_status-set-pnum-0-on-error.patch new file mode 100644 index 0000000..b8299ea --- /dev/null +++ b/SOURCES/kvm-block-get_block_status-set-pnum-0-on-error.patch @@ -0,0 +1,49 @@ +From d7a6dbe86fbbb30cc8142deb71763089aa1f2b62 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:49 +0200 +Subject: [PATCH 24/81] block/get_block_status: set *pnum = 0 on error + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-25-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55007 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 24/26] block/get_block_status: set *pnum = 0 on error +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +From: Peter Lieven + +if the call is invoked through bdrv_is_allocated the caller might +expect *pnum = 0 on error. however, a new implementation of +bdrv_get_block_status might only return a negative exit value on +error while keeping *pnum untouched. + +Reviewed-by: Eric Blake +Signed-off-by: Peter Lieven +Signed-off-by: Kevin Wolf +(cherry picked from commit 3e0a233d869e74e78b516be34715b91528508cfc) +--- + block.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/block.c b/block.c +index f993b2e..02e111e 100644 +--- a/block.c ++++ b/block.c +@@ -3069,6 +3069,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + + ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); + if (ret < 0) { ++ *pnum = 0; + return ret; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-introduce-bdrv_get_block_status-API.patch b/SOURCES/kvm-block-introduce-bdrv_get_block_status-API.patch new file mode 100644 index 0000000..4f42a36 --- /dev/null +++ b/SOURCES/kvm-block-introduce-bdrv_get_block_status-API.patch @@ -0,0 +1,447 @@ +From 89e6ba9d5ad137ecb8f981f1ec28ee519812bf50 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 6 Nov 2013 12:37:43 +0100 +Subject: [PATCH 12/81] block: introduce bdrv_get_block_status API + +RH-Author: Paolo Bonzini +Message-id: <1383741463-25811-1-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55521 +O-Subject: [RHEL 7.0 qemu-kvm PATCH v2 12/26] block: introduce bdrv_get_block_status API +Bugzilla: 989646 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +For now, bdrv_get_block_status is just another name for bdrv_is_allocated. +The next patches will add more flags. + +This also touches all block drivers with a mostly mechanical rename. The +sole exception is cow; because it calls cow_co_is_allocated from the read +code, we keep that function and make cow_co_get_block_status a wrapper. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit b6b8a33354a448ee421f57676c1a93a536a63269) +--- + block.c | 46 ++++++++++++++++++++++++++-------------------- + block/cow.c | 8 +++++++- + block/qcow.c | 4 ++-- + block/qcow2.c | 4 ++-- + block/qed.c | 4 ++-- + block/raw-posix.c | 4 ++-- + block/raw.c | 6 +++--- + block/sheepdog.c | 12 ++++++------ + block/vdi.c | 4 ++-- + block/vmdk.c | 4 ++-- + block/vvfat.c | 4 ++-- + include/block/block.h | 2 ++ + include/block/block_int.h | 2 +- + 13 files changed, 59 insertions(+), 45 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 46 +++++++++++++++++++++++++------------------- + block/cow.c | 8 ++++++- + block/qcow.c | 4 +- + block/qcow2.c | 4 +- + block/qed.c | 4 +- + block/raw-posix.c | 4 +- + block/raw.c | 6 ++-- + block/sheepdog.c | 12 +++++----- + block/vdi.c | 4 +- + block/vmdk.c | 4 +- + block/vvfat.c | 4 +- + include/block/block.h | 2 + + include/block/block_int.h | 2 +- + 13 files changed, 59 insertions(+), 45 deletions(-) + +diff --git a/block.c b/block.c +index f5d6658..772f5b7 100644 +--- a/block.c ++++ b/block.c +@@ -3010,15 +3010,15 @@ int bdrv_has_zero_init(BlockDriverState *bs) + return 1; + } + +-typedef struct BdrvCoIsAllocatedData { ++typedef struct BdrvCoGetBlockStatusData { + BlockDriverState *bs; + BlockDriverState *base; + int64_t sector_num; + int nb_sectors; + int *pnum; +- int ret; ++ int64_t ret; + bool done; +-} BdrvCoIsAllocatedData; ++} BdrvCoGetBlockStatusData; + + /* + * Returns true iff the specified sector is present in the disk image. Drivers +@@ -3035,9 +3035,9 @@ typedef struct BdrvCoIsAllocatedData { + * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes + * beyond the end of the disk image it will be clamped. + */ +-static int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, +- int64_t sector_num, +- int nb_sectors, int *pnum) ++static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, ++ int64_t sector_num, ++ int nb_sectors, int *pnum) + { + int64_t length; + int64_t n; +@@ -3057,35 +3057,35 @@ static int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, + nb_sectors = n; + } + +- if (!bs->drv->bdrv_co_is_allocated) { ++ if (!bs->drv->bdrv_co_get_block_status) { + *pnum = nb_sectors; + return 1; + } + +- return bs->drv->bdrv_co_is_allocated(bs, sector_num, nb_sectors, pnum); ++ return bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); + } + +-/* Coroutine wrapper for bdrv_is_allocated() */ +-static void coroutine_fn bdrv_is_allocated_co_entry(void *opaque) ++/* Coroutine wrapper for bdrv_get_block_status() */ ++static void coroutine_fn bdrv_get_block_status_co_entry(void *opaque) + { +- BdrvCoIsAllocatedData *data = opaque; ++ BdrvCoGetBlockStatusData *data = opaque; + BlockDriverState *bs = data->bs; + +- data->ret = bdrv_co_is_allocated(bs, data->sector_num, data->nb_sectors, +- data->pnum); ++ data->ret = bdrv_co_get_block_status(bs, data->sector_num, data->nb_sectors, ++ data->pnum); + data->done = true; + } + + /* +- * Synchronous wrapper around bdrv_co_is_allocated(). ++ * Synchronous wrapper around bdrv_co_get_block_status(). + * +- * See bdrv_co_is_allocated() for details. ++ * See bdrv_co_get_block_status() for details. + */ +-int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, +- int *pnum) ++int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, ++ int nb_sectors, int *pnum) + { + Coroutine *co; +- BdrvCoIsAllocatedData data = { ++ BdrvCoGetBlockStatusData data = { + .bs = bs, + .sector_num = sector_num, + .nb_sectors = nb_sectors, +@@ -3095,9 +3095,9 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + + if (qemu_in_coroutine()) { + /* Fast-path if already in coroutine context */ +- bdrv_is_allocated_co_entry(&data); ++ bdrv_get_block_status_co_entry(&data); + } else { +- co = qemu_coroutine_create(bdrv_is_allocated_co_entry); ++ co = qemu_coroutine_create(bdrv_get_block_status_co_entry); + qemu_coroutine_enter(co, &data); + while (!data.done) { + qemu_aio_wait(); +@@ -3106,6 +3106,12 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + return data.ret; + } + ++int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, ++ int nb_sectors, int *pnum) ++{ ++ return bdrv_get_block_status(bs, sector_num, nb_sectors, pnum); ++} ++ + /* + * Given an image chain: ... -> [BASE] -> [INTER1] -> [INTER2] -> [TOP] + * +diff --git a/block/cow.c b/block/cow.c +index 5a33b46..5e71c76 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -188,6 +188,12 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs, + return changed; + } + ++static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs, ++ int64_t sector_num, int nb_sectors, int *num_same) ++{ ++ return cow_co_is_allocated(bs, sector_num, nb_sectors, num_same); ++} ++ + static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num, + int nb_sectors) + { +@@ -370,7 +376,7 @@ static BlockDriver bdrv_cow = { + + .bdrv_read = cow_co_read, + .bdrv_write = cow_co_write, +- .bdrv_co_is_allocated = cow_co_is_allocated, ++ .bdrv_co_get_block_status = cow_co_get_block_status, + + .create_options = cow_create_options, + }; +diff --git a/block/qcow.c b/block/qcow.c +index e2a64c7..05af25c 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -395,7 +395,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, + return cluster_offset; + } + +-static int coroutine_fn qcow_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *pnum) + { + BDRVQcowState *s = bs->opaque; +@@ -895,7 +895,7 @@ static BlockDriver bdrv_qcow = { + + .bdrv_co_readv = qcow_co_readv, + .bdrv_co_writev = qcow_co_writev, +- .bdrv_co_is_allocated = qcow_co_is_allocated, ++ .bdrv_co_get_block_status = qcow_co_get_block_status, + + .bdrv_set_key = qcow_set_key, + .bdrv_make_empty = qcow_make_empty, +diff --git a/block/qcow2.c b/block/qcow2.c +index f6e64d2..8d3bf5d 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -640,7 +640,7 @@ static int qcow2_reopen_prepare(BDRVReopenState *state, + return 0; + } + +-static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *pnum) + { + BDRVQcowState *s = bs->opaque; +@@ -1786,7 +1786,7 @@ static BlockDriver bdrv_qcow2 = { + .bdrv_close = qcow2_close, + .bdrv_reopen_prepare = qcow2_reopen_prepare, + .bdrv_create = qcow2_create, +- .bdrv_co_is_allocated = qcow2_co_is_allocated, ++ .bdrv_co_get_block_status = qcow2_co_get_block_status, + .bdrv_set_key = qcow2_set_key, + .bdrv_make_empty = qcow2_make_empty, + +diff --git a/block/qed.c b/block/qed.c +index 4651403..a573039 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -667,7 +667,7 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l + } + } + +-static int coroutine_fn bdrv_qed_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { +@@ -1574,7 +1574,7 @@ static BlockDriver bdrv_qed = { + .bdrv_close = bdrv_qed_close, + .bdrv_reopen_prepare = bdrv_qed_reopen_prepare, + .bdrv_create = bdrv_qed_create, +- .bdrv_co_is_allocated = bdrv_qed_co_is_allocated, ++ .bdrv_co_get_block_status = bdrv_qed_co_get_block_status, + .bdrv_make_empty = bdrv_qed_make_empty, + .bdrv_aio_readv = bdrv_qed_aio_readv, + .bdrv_aio_writev = bdrv_qed_aio_writev, +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 90ce9f8..9a7c5a8 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -1084,7 +1084,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) + * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes + * beyond the end of the disk image it will be clamped. + */ +-static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { +@@ -1199,7 +1199,7 @@ static BlockDriver bdrv_file = { + .bdrv_reopen_abort = raw_reopen_abort, + .bdrv_close = raw_close, + .bdrv_create = raw_create, +- .bdrv_co_is_allocated = raw_co_is_allocated, ++ .bdrv_co_get_block_status = raw_co_get_block_status, + + .bdrv_aio_readv = raw_aio_readv, + .bdrv_aio_writev = raw_aio_writev, +diff --git a/block/raw.c b/block/raw.c +index f78ff39..844a222 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -35,11 +35,11 @@ static void raw_close(BlockDriverState *bs) + { + } + +-static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { +- return bdrv_is_allocated(bs->file, sector_num, nb_sectors, pnum); ++ return bdrv_get_block_status(bs->file, sector_num, nb_sectors, pnum); + } + + static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, +@@ -134,7 +134,7 @@ static BlockDriver bdrv_raw = { + + .bdrv_co_readv = raw_co_readv, + .bdrv_co_writev = raw_co_writev, +- .bdrv_co_is_allocated = raw_co_is_allocated, ++ .bdrv_co_get_block_status = raw_co_get_block_status, + .bdrv_co_write_zeroes = raw_co_write_zeroes, + .bdrv_co_discard = raw_co_discard, + +diff --git a/block/sheepdog.c b/block/sheepdog.c +index 2758c26..e5398bb 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -2289,9 +2289,9 @@ static coroutine_fn int sd_co_discard(BlockDriverState *bs, int64_t sector_num, + return acb->ret; + } + +-static coroutine_fn int +-sd_co_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, +- int *pnum) ++static coroutine_fn int64_t ++sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, ++ int *pnum) + { + BDRVSheepdogState *s = bs->opaque; + SheepdogInode *inode = &s->inode; +@@ -2356,7 +2356,7 @@ static BlockDriver bdrv_sheepdog = { + .bdrv_co_writev = sd_co_writev, + .bdrv_co_flush_to_disk = sd_co_flush_to_disk, + .bdrv_co_discard = sd_co_discard, +- .bdrv_co_is_allocated = sd_co_is_allocated, ++ .bdrv_co_get_block_status = sd_co_get_block_status, + + .bdrv_snapshot_create = sd_snapshot_create, + .bdrv_snapshot_goto = sd_snapshot_goto, +@@ -2383,7 +2383,7 @@ static BlockDriver bdrv_sheepdog_tcp = { + .bdrv_co_writev = sd_co_writev, + .bdrv_co_flush_to_disk = sd_co_flush_to_disk, + .bdrv_co_discard = sd_co_discard, +- .bdrv_co_is_allocated = sd_co_is_allocated, ++ .bdrv_co_get_block_status = sd_co_get_block_status, + + .bdrv_snapshot_create = sd_snapshot_create, + .bdrv_snapshot_goto = sd_snapshot_goto, +@@ -2410,7 +2410,7 @@ static BlockDriver bdrv_sheepdog_unix = { + .bdrv_co_writev = sd_co_writev, + .bdrv_co_flush_to_disk = sd_co_flush_to_disk, + .bdrv_co_discard = sd_co_discard, +- .bdrv_co_is_allocated = sd_co_is_allocated, ++ .bdrv_co_get_block_status = sd_co_get_block_status, + + .bdrv_snapshot_create = sd_snapshot_create, + .bdrv_snapshot_goto = sd_snapshot_goto, +diff --git a/block/vdi.c b/block/vdi.c +index 2662d89..1252ad4 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -470,7 +470,7 @@ static int vdi_reopen_prepare(BDRVReopenState *state, + return 0; + } + +-static int coroutine_fn vdi_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *pnum) + { + /* TODO: Check for too large sector_num (in bdrv_is_allocated or here). */ +@@ -779,7 +779,7 @@ static BlockDriver bdrv_vdi = { + .bdrv_close = vdi_close, + .bdrv_reopen_prepare = vdi_reopen_prepare, + .bdrv_create = vdi_create, +- .bdrv_co_is_allocated = vdi_co_is_allocated, ++ .bdrv_co_get_block_status = vdi_co_get_block_status, + .bdrv_make_empty = vdi_make_empty, + + .bdrv_read = vdi_co_read, +diff --git a/block/vmdk.c b/block/vmdk.c +index 66735ab..a30c3b9 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1042,7 +1042,7 @@ static VmdkExtent *find_extent(BDRVVmdkState *s, + return NULL; + } + +-static int coroutine_fn vmdk_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *pnum) + { + BDRVVmdkState *s = bs->opaque; +@@ -1820,7 +1820,7 @@ static BlockDriver bdrv_vmdk = { + .bdrv_close = vmdk_close, + .bdrv_create = vmdk_create, + .bdrv_co_flush_to_disk = vmdk_co_flush, +- .bdrv_co_is_allocated = vmdk_co_is_allocated, ++ .bdrv_co_get_block_status = vmdk_co_get_block_status, + .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, + + .create_options = vmdk_create_options, +diff --git a/block/vvfat.c b/block/vvfat.c +index 87b0279..510a559 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2874,7 +2874,7 @@ static coroutine_fn int vvfat_co_write(BlockDriverState *bs, int64_t sector_num, + return ret; + } + +-static int coroutine_fn vvfat_co_is_allocated(BlockDriverState *bs, ++static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int* n) + { + BDRVVVFATState* s = bs->opaque; +@@ -2981,7 +2981,7 @@ static BlockDriver bdrv_vvfat = { + + .bdrv_read = vvfat_co_read, + .bdrv_write = vvfat_co_write, +- .bdrv_co_is_allocated = vvfat_co_is_allocated, ++ .bdrv_co_get_block_status = vvfat_co_get_block_status, + }; + + static void bdrv_vvfat_init(void) +diff --git a/include/block/block.h b/include/block/block.h +index ec4d4aa..a733f5f 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -281,6 +281,8 @@ void bdrv_drain_all(void); + int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); + int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors); + int bdrv_has_zero_init(BlockDriverState *bs); ++int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num, ++ int nb_sectors, int *pnum); + int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + int *pnum); + int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 267be48..ea2c811 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -124,7 +124,7 @@ struct BlockDriver { + int64_t sector_num, int nb_sectors); + int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs, + int64_t sector_num, int nb_sectors); +- int coroutine_fn (*bdrv_co_is_allocated)(BlockDriverState *bs, ++ int64_t coroutine_fn (*bdrv_co_get_block_status)(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *pnum); + + /* +-- +1.7.1 + diff --git a/SOURCES/kvm-block-keep-bs-total_sectors-up-to-date-even-for-grow.patch b/SOURCES/kvm-block-keep-bs-total_sectors-up-to-date-even-for-grow.patch new file mode 100644 index 0000000..696d19d --- /dev/null +++ b/SOURCES/kvm-block-keep-bs-total_sectors-up-to-date-even-for-grow.patch @@ -0,0 +1,55 @@ +From 1c16f135463077e596b9156439d2482a1a8aa9b8 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:29 +0200 +Subject: [PATCH 04/81] block: keep bs->total_sectors up to date even for growable block devices + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-5-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54986 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 04/26] block: keep bs->total_sectors up to date even for growable block devices +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +If a BlockDriverState is growable, after every write we need to +check if bs->total_sectors might have changed. With this change, +bdrv_getlength does not need anymore a system call. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit df2a6f29a5019707d69f6eeb30cf792841cae5aa) +--- + block.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 2ba9a0a..d5aeff7 100644 +--- a/block.c ++++ b/block.c +@@ -2703,6 +2703,9 @@ static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs, + if (bs->wr_highest_sector < sector_num + nb_sectors - 1) { + bs->wr_highest_sector = sector_num + nb_sectors - 1; + } ++ if (bs->growable && ret >= 0) { ++ bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors); ++ } + + tracked_request_end(&req); + +@@ -2777,7 +2780,7 @@ int64_t bdrv_getlength(BlockDriverState *bs) + if (!drv) + return -ENOMEDIUM; + +- if (bs->growable || bdrv_dev_has_removable_media(bs)) { ++ if (bdrv_dev_has_removable_media(bs)) { + if (drv->bdrv_getlength) { + return drv->bdrv_getlength(bs); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-look-for-zero-blocks-in-bs-file.patch b/SOURCES/kvm-block-look-for-zero-blocks-in-bs-file.patch new file mode 100644 index 0000000..d78f093 --- /dev/null +++ b/SOURCES/kvm-block-look-for-zero-blocks-in-bs-file.patch @@ -0,0 +1,63 @@ +From 91a73a0f154a7d8f2c4949ea882f684d55c916e4 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:47 +0200 +Subject: [PATCH 22/81] block: look for zero blocks in bs->file + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-23-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55005 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 22/26] block: look for zero blocks in bs->file +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 5daa74a6ebce7543aaad178c4061dc087bb4c705) +--- + block.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 16 +++++++++++++++- + 1 files changed, 15 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 2a4a9dd..f993b2e 100644 +--- a/block.c ++++ b/block.c +@@ -3041,7 +3041,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + { + int64_t length; + int64_t n; +- int64_t ret; ++ int64_t ret, ret2; + + length = bdrv_getlength(bs); + if (length < 0) { +@@ -3083,6 +3083,20 @@ 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)) { ++ ret2 = bdrv_co_get_block_status(bs->file, ret >> BDRV_SECTOR_BITS, ++ *pnum, pnum); ++ if (ret2 >= 0) { ++ /* Ignore errors. This is just providing extra information, it ++ * is useful but not necessary. ++ */ ++ ret |= (ret2 & BDRV_BLOCK_ZERO); ++ } ++ } ++ + return ret; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-make-all-steps-in-qmp_transaction-as-callback.patch b/SOURCES/kvm-block-make-all-steps-in-qmp_transaction-as-callback.patch new file mode 100644 index 0000000..1883272 --- /dev/null +++ b/SOURCES/kvm-block-make-all-steps-in-qmp_transaction-as-callback.patch @@ -0,0 +1,206 @@ +From 2b05ad88980acb91357598f5ed041ec33aec0de6 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:56 +0200 +Subject: [PATCH 05/38] block: make all steps in qmp_transaction() as callback + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-6-git-send-email-kwolf@redhat.com> +Patchwork-id: 54192 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 05/32] block: make all steps in qmp_transaction() as callback +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Wenchao Xia + +Bugzilla: 1005818 + +Make it easier to add other operations to qmp_transaction() by using +callbacks, with external snapshots serving as an example implementation +of the callbacks. + +Signed-off-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit ba0c86a34e29b31ef360feda74c94200a5403fdd) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 71 insertions(+), 24 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 95 ++++++++++++++++++++++++++++++++++++++++++++--------------- + 1 files changed, 71 insertions(+), 24 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index b040f0f..b8521c7 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -779,14 +779,43 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, + + + /* New and old BlockDriverState structs for group snapshots */ +-typedef struct BlkTransactionStates { ++ ++typedef struct BlkTransactionStates BlkTransactionStates; ++ ++/* Only prepare() may fail. In a single transaction, only one of commit() or ++ abort() will be called, clean() will always be called if it present. */ ++typedef struct BdrvActionOps { ++ /* Size of state struct, in bytes. */ ++ size_t instance_size; ++ /* Prepare the work, must NOT be NULL. */ ++ void (*prepare)(BlkTransactionStates *common, Error **errp); ++ /* Commit the changes, must NOT be NULL. */ ++ void (*commit)(BlkTransactionStates *common); ++ /* Abort the changes on fail, can be NULL. */ ++ void (*abort)(BlkTransactionStates *common); ++ /* Clean up resource in the end, can be NULL. */ ++ void (*clean)(BlkTransactionStates *common); ++} BdrvActionOps; ++ ++/* ++ * This structure must be arranged as first member in child type, assuming ++ * that compiler will also arrange it to the same address with parent instance. ++ * Later it will be used in free(). ++ */ ++struct BlkTransactionStates { ++ BlockdevAction *action; ++ const BdrvActionOps *ops; ++ QSIMPLEQ_ENTRY(BlkTransactionStates) entry; ++}; ++ ++/* external snapshot private data */ ++typedef struct ExternalSnapshotStates { ++ BlkTransactionStates common; + BlockDriverState *old_bs; + BlockDriverState *new_bs; +- QSIMPLEQ_ENTRY(BlkTransactionStates) entry; +-} BlkTransactionStates; ++} ExternalSnapshotStates; + +-static void external_snapshot_prepare(BlockdevAction *action, +- BlkTransactionStates *states, ++static void external_snapshot_prepare(BlkTransactionStates *common, + Error **errp) + { + BlockDriver *proto_drv; +@@ -797,6 +826,9 @@ static void external_snapshot_prepare(BlockdevAction *action, + const char *new_image_file; + const char *format = "qcow2"; + enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; ++ ExternalSnapshotStates *states = ++ DO_UPCAST(ExternalSnapshotStates, common, common); ++ BlockdevAction *action = common->action; + + /* get parameters */ + g_assert(action->kind == BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); +@@ -871,8 +903,11 @@ static void external_snapshot_prepare(BlockdevAction *action, + } + } + +-static void external_snapshot_commit(BlkTransactionStates *states) ++static void external_snapshot_commit(BlkTransactionStates *common) + { ++ ExternalSnapshotStates *states = ++ DO_UPCAST(ExternalSnapshotStates, common, common); ++ + /* This removes our old bs from the bdrv_states, and adds the new bs */ + bdrv_append(states->new_bs, states->old_bs); + /* We don't need (or want) to use the transactional +@@ -882,13 +917,24 @@ static void external_snapshot_commit(BlkTransactionStates *states) + NULL); + } + +-static void external_snapshot_abort(BlkTransactionStates *states) ++static void external_snapshot_abort(BlkTransactionStates *common) + { ++ ExternalSnapshotStates *states = ++ DO_UPCAST(ExternalSnapshotStates, common, common); + if (states->new_bs) { + bdrv_delete(states->new_bs); + } + } + ++static const BdrvActionOps actions[] = { ++ [BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC] = { ++ .instance_size = sizeof(ExternalSnapshotStates), ++ .prepare = external_snapshot_prepare, ++ .commit = external_snapshot_commit, ++ .abort = external_snapshot_abort, ++ }, ++}; ++ + /* + * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail + * then we do not pivot any of the devices in the group, and abandon the +@@ -909,32 +955,28 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + /* We don't do anything in this loop that commits us to the snapshot */ + while (NULL != dev_entry) { + BlockdevAction *dev_info = NULL; ++ const BdrvActionOps *ops; + + dev_info = dev_entry->value; + dev_entry = dev_entry->next; + +- states = g_malloc0(sizeof(BlkTransactionStates)); ++ assert(dev_info->kind < ARRAY_SIZE(actions)); ++ ++ ops = &actions[dev_info->kind]; ++ states = g_malloc0(ops->instance_size); ++ states->ops = ops; ++ states->action = dev_info; + QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, states, entry); + +- switch (dev_info->kind) { +- case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC: +- external_snapshot_prepare(dev_info, states, errp); +- if (error_is_set(&local_err)) { +- error_propagate(errp, local_err); +- goto delete_and_fail; +- } +- break; +- default: +- abort(); ++ states->ops->prepare(states, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ goto delete_and_fail; + } +- + } + +- +- /* Now we are going to do the actual pivot. Everything up to this point +- * is reversible, but we are committed at this point */ + QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { +- external_snapshot_commit(states); ++ states->ops->commit(states); + } + + /* success */ +@@ -946,10 +988,15 @@ delete_and_fail: + * the original bs for all images + */ + QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { +- external_snapshot_abort(states); ++ if (states->ops->abort) { ++ states->ops->abort(states); ++ } + } + exit: + QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) { ++ if (states->ops->clean) { ++ states->ops->clean(states); ++ } + g_free(states); + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-make-bdrv_co_is_allocated-static.patch b/SOURCES/kvm-block-make-bdrv_co_is_allocated-static.patch new file mode 100644 index 0000000..bcfa9cf --- /dev/null +++ b/SOURCES/kvm-block-make-bdrv_co_is_allocated-static.patch @@ -0,0 +1,129 @@ +From 9b3702c45245f7bbb51350c25e8cf304c490b96a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 7 Nov 2013 07:19:42 +0100 +Subject: [PATCH 05/81] block: make bdrv_co_is_allocated static + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-6-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54988 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 05/26] block: make bdrv_co_is_allocated static +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +bdrv_is_allocated can detect coroutine context and go through a fast +path, similar to other block layer functions. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit bdad13b9deec47d5d9eaf7f43867d19a79471244) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 24 +++++++++++++++--------- + block/raw.c | 2 +- + block/stream.c | 4 ++-- + include/block/block.h | 2 -- + 4 files changed, 18 insertions(+), 14 deletions(-) + +diff --git a/block.c b/block.c +index d5aeff7..0607cc6 100644 +--- a/block.c ++++ b/block.c +@@ -2555,7 +2555,7 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, + if (flags & BDRV_REQ_COPY_ON_READ) { + int pnum; + +- ret = bdrv_co_is_allocated(bs, sector_num, nb_sectors, &pnum); ++ ret = bdrv_is_allocated(bs, sector_num, nb_sectors, &pnum); + if (ret < 0) { + goto out; + } +@@ -3027,8 +3027,9 @@ typedef struct BdrvCoIsAllocatedData { + * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes + * beyond the end of the disk image it will be clamped. + */ +-int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num, +- int nb_sectors, int *pnum) ++static int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, ++ int64_t sector_num, ++ int nb_sectors, int *pnum) + { + int64_t n; + +@@ -3078,10 +3079,15 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + .done = false, + }; + +- co = qemu_coroutine_create(bdrv_is_allocated_co_entry); +- qemu_coroutine_enter(co, &data); +- while (!data.done) { +- qemu_aio_wait(); ++ if (qemu_in_coroutine()) { ++ /* Fast-path if already in coroutine context */ ++ bdrv_is_allocated_co_entry(&data); ++ } else { ++ co = qemu_coroutine_create(bdrv_is_allocated_co_entry); ++ qemu_coroutine_enter(co, &data); ++ while (!data.done) { ++ qemu_aio_wait(); ++ } + } + return data.ret; + } +@@ -3109,8 +3115,8 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, + intermediate = top; + while (intermediate && intermediate != base) { + int pnum_inter; +- ret = bdrv_co_is_allocated(intermediate, sector_num, nb_sectors, +- &pnum_inter); ++ ret = bdrv_is_allocated(intermediate, sector_num, nb_sectors, ++ &pnum_inter); + if (ret < 0) { + return ret; + } else if (ret) { +diff --git a/block/raw.c b/block/raw.c +index 8c81de9..f78ff39 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -39,7 +39,7 @@ static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) + { +- return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum); ++ return bdrv_is_allocated(bs->file, sector_num, nb_sectors, pnum); + } + + static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, +diff --git a/block/stream.c b/block/stream.c +index d6df06f..f8efa8a 100644 +--- a/block/stream.c ++++ b/block/stream.c +@@ -115,8 +115,8 @@ wait: + break; + } + +- ret = bdrv_co_is_allocated(bs, sector_num, +- STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n); ++ ret = bdrv_is_allocated(bs, sector_num, ++ STREAM_BUFFER_SIZE / BDRV_SECTOR_SIZE, &n); + if (ret == 1) { + /* Allocated in the top, no need to copy. */ + copy = false; +diff --git a/include/block/block.h b/include/block/block.h +index 1a3ed22..1932e67 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -192,8 +192,6 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, + */ + int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, + int nb_sectors); +-int coroutine_fn bdrv_co_is_allocated(BlockDriverState *bs, int64_t sector_num, +- int nb_sectors, int *pnum); + int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, + BlockDriverState *base, + int64_t sector_num, +-- +1.7.1 + diff --git a/SOURCES/kvm-block-make-bdrv_has_zero_init-return-false-for-copy-.patch b/SOURCES/kvm-block-make-bdrv_has_zero_init-return-false-for-copy-.patch new file mode 100644 index 0000000..c6c0345 --- /dev/null +++ b/SOURCES/kvm-block-make-bdrv_has_zero_init-return-false-for-copy-.patch @@ -0,0 +1,69 @@ +From 455a0cc4e93815b2cd2741554076029f2c365e25 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:36 +0200 +Subject: [PATCH 11/81] block: make bdrv_has_zero_init return false for copy-on-write-images + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-12-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54994 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 11/26] block: make bdrv_has_zero_init return false for copy-on-write-images +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +This helps implementing is_allocated on top of get_block_status. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 11212d8fa08a4e5bd56bb4f6877f9a4c0439a02b) +--- + block.c | 5 +++++ + qemu-img.c | 9 +-------- + 2 files changed, 6 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 5 +++++ + qemu-img.c | 9 +-------- + 2 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/block.c b/block.c +index d838a3c..f5d6658 100644 +--- a/block.c ++++ b/block.c +@@ -2998,6 +2998,11 @@ int bdrv_has_zero_init(BlockDriverState *bs) + { + assert(bs->drv); + ++ /* If BS is a copy on write image, it is initialized to ++ the contents of the base image, which may not be zeroes. */ ++ if (bs->backing_hd) { ++ return 0; ++ } + if (bs->drv->bdrv_has_zero_init) { + return bs->drv->bdrv_has_zero_init(bs); + } +diff --git a/qemu-img.c b/qemu-img.c +index 71cbc59..a9aabd5 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1511,14 +1511,7 @@ static int img_convert(int argc, char **argv) + should add a specific call to have the info to go faster */ + buf1 = buf; + while (n > 0) { +- /* If the output image is being created as a copy on write image, +- copy all sectors even the ones containing only NUL bytes, +- because they may differ from the sectors in the base image. +- +- If the output is to a host device, we also write out +- sectors that are entirely 0, since whatever data was +- already there is garbage, not 0s. */ +- if (!has_zero_init || out_baseimg || ++ if (!has_zero_init || + is_allocated_sectors_min(buf1, n, &n1, min_sparse)) { + ret = bdrv_write(out_bs, sector_num, buf1, n1); + if (ret < 0) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-migration-efficiently-encode-zero-blocks.patch b/SOURCES/kvm-block-migration-efficiently-encode-zero-blocks.patch new file mode 100644 index 0000000..3b5fa0f --- /dev/null +++ b/SOURCES/kvm-block-migration-efficiently-encode-zero-blocks.patch @@ -0,0 +1,183 @@ +From eb7381f07b22955557a2b7ea469c5bf5aa39281e Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:09 +0200 +Subject: [PATCH 14/25] block-migration: efficiently encode zero blocks + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-5-git-send-email-owasserm@redhat.com> +Patchwork-id: 54800 +O-Subject: [RHEL7.0 qemu-kvm v2 04/10] block-migration: efficiently encode zero blocks +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Peter Lieven + +this patch adds a efficient encoding for zero blocks by +adding a new flag indicating a block is completely zero. + +additionally bdrv_write_zeros() is used at the destination +to efficiently write these zeroes. depending on the implementation +this avoids that the destination target gets fully provisioned. + +Signed-off-by: Peter Lieven +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 323004a39d4d8d33c744a5b108f80bfe6402fca3) +Conflicts: + include/migration/migration.h + qapi-schema.json +--- + block-migration.c | 32 ++++++++++++++++++++++++++------ + include/migration/migration.h | 2 ++ + migration.c | 9 +++++++++ + qapi-schema.json | 8 +++++++- + 4 files changed, 44 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block-migration.c | 32 ++++++++++++++++++++++++++------ + include/migration/migration.h | 2 ++ + migration.c | 9 +++++++++ + qapi-schema.json | 8 +++++++- + 4 files changed, 44 insertions(+), 7 deletions(-) + +diff --git a/block-migration.c b/block-migration.c +index 2fd7699..f803f20 100644 +--- a/block-migration.c ++++ b/block-migration.c +@@ -29,6 +29,7 @@ + #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01 + #define BLK_MIG_FLAG_EOS 0x02 + #define BLK_MIG_FLAG_PROGRESS 0x04 ++#define BLK_MIG_FLAG_ZERO_BLOCK 0x08 + + #define MAX_IS_ALLOCATED_SEARCH 65536 + +@@ -80,6 +81,7 @@ typedef struct BlkMigState { + int shared_base; + QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list; + int64_t total_sector_sum; ++ bool zero_blocks; + + /* Protected by lock. */ + QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list; +@@ -114,16 +116,30 @@ static void blk_mig_unlock(void) + static void blk_send(QEMUFile *f, BlkMigBlock * blk) + { + int len; ++ uint64_t flags = BLK_MIG_FLAG_DEVICE_BLOCK; ++ ++ if (block_mig_state.zero_blocks && ++ buffer_is_zero(blk->buf, BLOCK_SIZE)) { ++ flags |= BLK_MIG_FLAG_ZERO_BLOCK; ++ } + + /* sector number and flags */ + qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS) +- | BLK_MIG_FLAG_DEVICE_BLOCK); ++ | flags); + + /* device name */ + len = strlen(blk->bmds->bs->device_name); + qemu_put_byte(f, len); + qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len); + ++ /* if a block is zero we need to flush here since the network ++ * bandwidth is now a lot higher than the storage device bandwidth. ++ * thus if we queue zero blocks we slow down the migration */ ++ if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { ++ qemu_fflush(f); ++ return; ++ } ++ + qemu_put_buffer(f, blk->buf, BLOCK_SIZE); + } + +@@ -344,6 +360,7 @@ static void init_blk_migration(QEMUFile *f) + block_mig_state.total_sector_sum = 0; + block_mig_state.prev_progress = -1; + block_mig_state.bulk_completed = 0; ++ block_mig_state.zero_blocks = migrate_zero_blocks(); + + bdrv_iterate(init_blk_migration_it, NULL); + } +@@ -762,12 +779,15 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) + nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK; + } + +- buf = g_malloc(BLOCK_SIZE); +- +- qemu_get_buffer(f, buf, BLOCK_SIZE); +- ret = bdrv_write(bs, addr, buf, nr_sectors); ++ if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { ++ ret = bdrv_write_zeroes(bs, addr, nr_sectors); ++ } else { ++ buf = g_malloc(BLOCK_SIZE); ++ qemu_get_buffer(f, buf, BLOCK_SIZE); ++ ret = bdrv_write(bs, addr, buf, nr_sectors); ++ g_free(buf); ++ } + +- g_free(buf); + if (ret < 0) { + return ret; + } +diff --git a/include/migration/migration.h b/include/migration/migration.h +index 1fc2666..f1519dd 100644 +--- a/include/migration/migration.h ++++ b/include/migration/migration.h +@@ -119,6 +119,8 @@ void migrate_add_blocker(Error *reason); + */ + void migrate_del_blocker(Error *reason); + ++bool migrate_zero_blocks(void); ++ + bool migrate_auto_converge(void); + + int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, +diff --git a/migration.c b/migration.c +index 177fc22..cc0e649 100644 +--- a/migration.c ++++ b/migration.c +@@ -483,6 +483,15 @@ bool migrate_auto_converge(void) + return s->enabled_capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; + } + ++bool migrate_zero_blocks(void) ++{ ++ MigrationState *s; ++ ++ s = migrate_get_current(); ++ ++ return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; ++} ++ + int migrate_use_xbzrle(void) + { + MigrationState *s; +diff --git a/qapi-schema.json b/qapi-schema.json +index 3936337..a717fbf 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -605,10 +605,16 @@ + # @auto-converge: If enabled, QEMU will automatically throttle down the guest + # to speed up convergence of RAM migration. (since 1.6) + # ++# @zero-blocks: During storage migration encode blocks of zeroes efficiently. This ++# essentially saves 1MB of zeroes per block on the wire. Enabling requires ++# source and target VM to support this feature. To enable it is sufficient ++# to enable the capability on the source VM. The feature is disabled by ++# default. (since 1.6) ++# + # Since: 1.2 + ## + { 'enum': 'MigrationCapability', +- 'data': ['xbzrle', 'auto-converge'] } ++ 'data': ['xbzrle', 'auto-converge', 'zero-blocks'] } + + ## + # @MigrationCapabilityStatus +-- +1.7.1 + diff --git a/SOURCES/kvm-block-mirror_complete-use-error_setg_file_open.patch b/SOURCES/kvm-block-mirror_complete-use-error_setg_file_open.patch new file mode 100644 index 0000000..45acb01 --- /dev/null +++ b/SOURCES/kvm-block-mirror_complete-use-error_setg_file_open.patch @@ -0,0 +1,46 @@ +From 6793e07d618e99a30d8cc13cc53970f7cd5f0aa9 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:25 +0100 +Subject: [PATCH 06/29] block: mirror_complete(): use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-3-git-send-email-lersek@redhat.com> +Patchwork-id: 55192 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/8] block: mirror_complete(): use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Reviewed-by: Stefan Hajnoczi +Acked-by: Kevin Wolf +(cherry picked from commit dacc26aae5d291317a3277970a4f39a562939a78) +Signed-off-by: Laszlo Ersek +--- + block/mirror.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/mirror.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block/mirror.c b/block/mirror.c +index 8b07dec..1ae724f 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -512,7 +512,7 @@ static void mirror_complete(BlockJob *job, Error **errp) + char backing_filename[PATH_MAX]; + bdrv_get_full_backing_filename(s->target, backing_filename, + sizeof(backing_filename)); +- error_set(errp, QERR_OPEN_FILE_FAILED, backing_filename); ++ error_setg_file_open(errp, -ret, backing_filename); + return; + } + if (!s->synced) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-move-input-parsing-code-in-qmp_transaction.patch b/SOURCES/kvm-block-move-input-parsing-code-in-qmp_transaction.patch new file mode 100644 index 0000000..ce82d2d --- /dev/null +++ b/SOURCES/kvm-block-move-input-parsing-code-in-qmp_transaction.patch @@ -0,0 +1,112 @@ +From 80e1dce1b2b514b1553f6d02194110db0d330c2d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:53 +0200 +Subject: [PATCH 02/38] block: move input parsing code in qmp_transaction() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-3-git-send-email-kwolf@redhat.com> +Patchwork-id: 54189 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 02/32] block: move input parsing code in qmp_transaction() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Wenchao Xia + +Bugzilla: 1005818 + +The code is moved into preparation function, and changed +a bit to tip more clearly what it is doing. + +Signed-off-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit e2a31e8798e8246bed8ab396a71cd06bf95edde6) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 38 +++++++++++++++++++------------------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 38 +++++++++++++++++++------------------- + 1 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 1bff654..9eab803 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -785,10 +785,7 @@ typedef struct BlkTransactionStates { + QSIMPLEQ_ENTRY(BlkTransactionStates) entry; + } BlkTransactionStates; + +-static void external_snapshot_prepare(const char *device, +- const char *format, +- const char *new_image_file, +- enum NewImageMode mode, ++static void external_snapshot_prepare(BlockdevAction *action, + BlkTransactionStates *states, + Error **errp) + { +@@ -796,7 +793,24 @@ static void external_snapshot_prepare(const char *device, + BlockDriver *drv; + int flags, ret; + Error *local_err = NULL; ++ const char *device; ++ const char *new_image_file; ++ const char *format = "qcow2"; ++ enum NewImageMode mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + ++ /* get parameters */ ++ g_assert(action->kind == BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC); ++ ++ device = action->blockdev_snapshot_sync->device; ++ new_image_file = action->blockdev_snapshot_sync->snapshot_file; ++ if (action->blockdev_snapshot_sync->has_format) { ++ format = action->blockdev_snapshot_sync->format; ++ } ++ if (action->blockdev_snapshot_sync->has_mode) { ++ mode = action->blockdev_snapshot_sync->mode; ++ } ++ ++ /* start processing */ + drv = bdrv_find_format(format); + if (!drv) { + error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); +@@ -877,10 +891,6 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + /* We don't do anything in this loop that commits us to the snapshot */ + while (NULL != dev_entry) { + BlockdevAction *dev_info = NULL; +- enum NewImageMode mode; +- const char *new_image_file; +- const char *device; +- const char *format = "qcow2"; + + dev_info = dev_entry->value; + dev_entry = dev_entry->next; +@@ -890,17 +900,7 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + + switch (dev_info->kind) { + case BLOCKDEV_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC: +- device = dev_info->blockdev_snapshot_sync->device; +- if (!dev_info->blockdev_snapshot_sync->has_mode) { +- dev_info->blockdev_snapshot_sync->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; +- } +- new_image_file = dev_info->blockdev_snapshot_sync->snapshot_file; +- if (dev_info->blockdev_snapshot_sync->has_format) { +- format = dev_info->blockdev_snapshot_sync->format; +- } +- mode = dev_info->blockdev_snapshot_sync->mode; +- external_snapshot_prepare(device, format, new_image_file, +- mode, states, &local_err); ++ external_snapshot_prepare(dev_info, states, errp); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + goto delete_and_fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-move-qmp-and-info-dump-related-code-to-block-q.patch b/SOURCES/kvm-block-move-qmp-and-info-dump-related-code-to-block-q.patch new file mode 100644 index 0000000..ea8066a --- /dev/null +++ b/SOURCES/kvm-block-move-qmp-and-info-dump-related-code-to-block-q.patch @@ -0,0 +1,931 @@ +From 9bba35d273d094e206e29f5a328f21834a838471 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 12:59:07 +0100 +Subject: [PATCH 68/87] block: move qmp and info dump related code to block/qapi.c + +RH-Author: Max Reitz +Message-id: <1383756824-6921-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 55557 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 02/21] block: move qmp and info dump related code to block/qapi.c +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Wenchao Xia + +BZ: 980771 + +This patch is a pure code move patch, except following modification: +1 get_human_readable_size() is changed to static function. +2 dump_human_image_info() is renamed to bdrv_image_info_dump(). +3 in qmp_query_block() and qmp_query_blockstats, use bdrv_next(bs) +instead of direct traverse of global array 'bdrv_states'. +4 collect_snapshots() and collect_image_info() are renamed, unused parameter +*fmt in collect_image_info() is removed. +5 code style fix. + +To avoid conflict and tip better, macro in header file is BLOCK_QAPI_H +instead of QAPI_H. Now block.h and snapshot.h are at the same level in +include path, block_int.h and qapi.h will both include them. + +Signed-off-by: Wenchao Xia +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit f364ec65b56b69c55b674cb6560aa1fbbea9e013) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block.c | 185 ----------------------- + block/Makefile.objs | 2 +- + block/qapi.c | 360 +++++++++++++++++++++++++++++++++++++++++++++ + include/block/block.h | 9 - + include/block/block_int.h | 1 + + include/block/qapi.h | 41 +++++ + qemu-img.c | 156 +------------------- + savevm.c | 1 + + 8 files changed, 408 insertions(+), 347 deletions(-) + create mode 100644 block/qapi.c + create mode 100644 include/block/qapi.h + +diff --git a/block.c b/block.c +index dccdb2c..e4885da 100644 +--- a/block.c ++++ b/block.c +@@ -3266,128 +3266,6 @@ int bdrv_is_allocated_above(BlockDriverState *top, + return 0; + } + +-BlockInfo *bdrv_query_info(BlockDriverState *bs) +-{ +- BlockInfo *info = g_malloc0(sizeof(*info)); +- info->device = g_strdup(bs->device_name); +- info->type = g_strdup("unknown"); +- info->locked = bdrv_dev_is_medium_locked(bs); +- info->removable = bdrv_dev_has_removable_media(bs); +- +- if (bdrv_dev_has_removable_media(bs)) { +- info->has_tray_open = true; +- info->tray_open = bdrv_dev_is_tray_open(bs); +- } +- +- if (bdrv_iostatus_is_enabled(bs)) { +- info->has_io_status = true; +- info->io_status = bs->iostatus; +- } +- +- if (bs->dirty_bitmap) { +- info->has_dirty = true; +- info->dirty = g_malloc0(sizeof(*info->dirty)); +- info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE; +- info->dirty->granularity = +- ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap)); +- } +- +- if (bs->drv) { +- info->has_inserted = true; +- info->inserted = g_malloc0(sizeof(*info->inserted)); +- info->inserted->file = g_strdup(bs->filename); +- info->inserted->ro = bs->read_only; +- info->inserted->drv = g_strdup(bs->drv->format_name); +- info->inserted->encrypted = bs->encrypted; +- info->inserted->encryption_key_missing = bdrv_key_required(bs); +- +- if (bs->backing_file[0]) { +- info->inserted->has_backing_file = true; +- info->inserted->backing_file = g_strdup(bs->backing_file); +- } +- +- info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs); +- +- if (bs->io_limits_enabled) { +- info->inserted->bps = +- bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; +- info->inserted->bps_rd = +- bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; +- info->inserted->bps_wr = +- bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; +- info->inserted->iops = +- bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; +- info->inserted->iops_rd = +- bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; +- info->inserted->iops_wr = +- bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; +- } +- } +- return info; +-} +- +-BlockInfoList *qmp_query_block(Error **errp) +-{ +- BlockInfoList *head = NULL, **p_next = &head; +- BlockDriverState *bs; +- +- QTAILQ_FOREACH(bs, &bdrv_states, list) { +- BlockInfoList *info = g_malloc0(sizeof(*info)); +- info->value = bdrv_query_info(bs); +- +- *p_next = info; +- p_next = &info->next; +- } +- +- return head; +-} +- +-BlockStats *bdrv_query_stats(const BlockDriverState *bs) +-{ +- BlockStats *s; +- +- s = g_malloc0(sizeof(*s)); +- +- if (bs->device_name[0]) { +- s->has_device = true; +- s->device = g_strdup(bs->device_name); +- } +- +- s->stats = g_malloc0(sizeof(*s->stats)); +- s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; +- s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; +- s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; +- s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; +- s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; +- s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; +- s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; +- s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; +- s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; +- +- if (bs->file) { +- s->has_parent = true; +- s->parent = bdrv_query_stats(bs->file); +- } +- +- return s; +-} +- +-BlockStatsList *qmp_query_blockstats(Error **errp) +-{ +- BlockStatsList *head = NULL, **p_next = &head; +- BlockDriverState *bs; +- +- QTAILQ_FOREACH(bs, &bdrv_states, list) { +- BlockStatsList *info = g_malloc0(sizeof(*info)); +- info->value = bdrv_query_stats(bs); +- +- *p_next = info; +- p_next = &info->next; +- } +- +- return head; +-} +- + const char *bdrv_get_encrypted_filename(BlockDriverState *bs) + { + if (bs->backing_hd && bs->backing_hd->encrypted) +@@ -3623,69 +3501,6 @@ BlockDriverState *bdrv_find_base(BlockDriverState *bs) + return curr_bs; + } + +-#define NB_SUFFIXES 4 +- +-char *get_human_readable_size(char *buf, int buf_size, int64_t size) +-{ +- static const char suffixes[NB_SUFFIXES] = "KMGT"; +- int64_t base; +- int i; +- +- if (size <= 999) { +- snprintf(buf, buf_size, "%" PRId64, size); +- } else { +- base = 1024; +- for(i = 0; i < NB_SUFFIXES; i++) { +- if (size < (10 * base)) { +- snprintf(buf, buf_size, "%0.1f%c", +- (double)size / base, +- suffixes[i]); +- break; +- } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { +- snprintf(buf, buf_size, "%" PRId64 "%c", +- ((size + (base >> 1)) / base), +- suffixes[i]); +- break; +- } +- base = base * 1024; +- } +- } +- return buf; +-} +- +-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) +-{ +- char buf1[128], date_buf[128], clock_buf[128]; +- struct tm tm; +- time_t ti; +- int64_t secs; +- +- if (!sn) { +- snprintf(buf, buf_size, +- "%-10s%-20s%7s%20s%15s", +- "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); +- } else { +- ti = sn->date_sec; +- localtime_r(&ti, &tm); +- strftime(date_buf, sizeof(date_buf), +- "%Y-%m-%d %H:%M:%S", &tm); +- secs = sn->vm_clock_nsec / 1000000000; +- snprintf(clock_buf, sizeof(clock_buf), +- "%02d:%02d:%02d.%03d", +- (int)(secs / 3600), +- (int)((secs / 60) % 60), +- (int)(secs % 60), +- (int)((sn->vm_clock_nsec / 1000000) % 1000)); +- snprintf(buf, buf_size, +- "%-10s%-20s%7s%20s%15s", +- sn->id_str, sn->name, +- get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size), +- date_buf, +- clock_buf); +- } +- return buf; +-} +- + /**************************************************************/ + /* async I/Os */ + +diff --git a/block/Makefile.objs b/block/Makefile.objs +index 162f270..3db1839 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -4,7 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o + block-obj-y += qed-check.o + block-obj-y += vhdx.o + block-obj-y += parallels.o blkdebug.o blkverify.o +-block-obj-y += snapshot.o ++block-obj-y += snapshot.o qapi.o + block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o + block-obj-$(CONFIG_POSIX) += raw-posix.o + block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o +diff --git a/block/qapi.c b/block/qapi.c +new file mode 100644 +index 0000000..155e77e +--- /dev/null ++++ b/block/qapi.c +@@ -0,0 +1,360 @@ ++/* ++ * Block layer qmp and info dump related functions ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "block/qapi.h" ++#include "block/block_int.h" ++#include "qmp-commands.h" ++ ++void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info) ++{ ++ int i, sn_count; ++ QEMUSnapshotInfo *sn_tab = NULL; ++ SnapshotInfoList *info_list, *cur_item = NULL; ++ sn_count = bdrv_snapshot_list(bs, &sn_tab); ++ ++ for (i = 0; i < sn_count; i++) { ++ info->has_snapshots = true; ++ info_list = g_new0(SnapshotInfoList, 1); ++ ++ info_list->value = g_new0(SnapshotInfo, 1); ++ info_list->value->id = g_strdup(sn_tab[i].id_str); ++ info_list->value->name = g_strdup(sn_tab[i].name); ++ info_list->value->vm_state_size = sn_tab[i].vm_state_size; ++ info_list->value->date_sec = sn_tab[i].date_sec; ++ info_list->value->date_nsec = sn_tab[i].date_nsec; ++ info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; ++ info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; ++ ++ /* XXX: waiting for the qapi to support qemu-queue.h types */ ++ if (!cur_item) { ++ info->snapshots = cur_item = info_list; ++ } else { ++ cur_item->next = info_list; ++ cur_item = info_list; ++ } ++ ++ } ++ ++ g_free(sn_tab); ++} ++ ++void bdrv_collect_image_info(BlockDriverState *bs, ++ ImageInfo *info, ++ const char *filename) ++{ ++ uint64_t total_sectors; ++ char backing_filename[1024]; ++ char backing_filename2[1024]; ++ BlockDriverInfo bdi; ++ ++ bdrv_get_geometry(bs, &total_sectors); ++ ++ info->filename = g_strdup(filename); ++ info->format = g_strdup(bdrv_get_format_name(bs)); ++ info->virtual_size = total_sectors * 512; ++ info->actual_size = bdrv_get_allocated_file_size(bs); ++ info->has_actual_size = info->actual_size >= 0; ++ if (bdrv_is_encrypted(bs)) { ++ info->encrypted = true; ++ info->has_encrypted = true; ++ } ++ if (bdrv_get_info(bs, &bdi) >= 0) { ++ if (bdi.cluster_size != 0) { ++ info->cluster_size = bdi.cluster_size; ++ info->has_cluster_size = true; ++ } ++ info->dirty_flag = bdi.is_dirty; ++ info->has_dirty_flag = true; ++ } ++ bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); ++ if (backing_filename[0] != '\0') { ++ info->backing_filename = g_strdup(backing_filename); ++ info->has_backing_filename = true; ++ bdrv_get_full_backing_filename(bs, backing_filename2, ++ sizeof(backing_filename2)); ++ ++ if (strcmp(backing_filename, backing_filename2) != 0) { ++ info->full_backing_filename = ++ g_strdup(backing_filename2); ++ info->has_full_backing_filename = true; ++ } ++ ++ if (bs->backing_format[0]) { ++ info->backing_filename_format = g_strdup(bs->backing_format); ++ info->has_backing_filename_format = true; ++ } ++ } ++} ++ ++BlockInfo *bdrv_query_info(BlockDriverState *bs) ++{ ++ BlockInfo *info = g_malloc0(sizeof(*info)); ++ info->device = g_strdup(bs->device_name); ++ info->type = g_strdup("unknown"); ++ info->locked = bdrv_dev_is_medium_locked(bs); ++ info->removable = bdrv_dev_has_removable_media(bs); ++ ++ if (bdrv_dev_has_removable_media(bs)) { ++ info->has_tray_open = true; ++ info->tray_open = bdrv_dev_is_tray_open(bs); ++ } ++ ++ if (bdrv_iostatus_is_enabled(bs)) { ++ info->has_io_status = true; ++ info->io_status = bs->iostatus; ++ } ++ ++ if (bs->dirty_bitmap) { ++ info->has_dirty = true; ++ info->dirty = g_malloc0(sizeof(*info->dirty)); ++ info->dirty->count = bdrv_get_dirty_count(bs) * BDRV_SECTOR_SIZE; ++ info->dirty->granularity = ++ ((int64_t) BDRV_SECTOR_SIZE << hbitmap_granularity(bs->dirty_bitmap)); ++ } ++ ++ if (bs->drv) { ++ info->has_inserted = true; ++ info->inserted = g_malloc0(sizeof(*info->inserted)); ++ info->inserted->file = g_strdup(bs->filename); ++ info->inserted->ro = bs->read_only; ++ info->inserted->drv = g_strdup(bs->drv->format_name); ++ info->inserted->encrypted = bs->encrypted; ++ info->inserted->encryption_key_missing = bdrv_key_required(bs); ++ ++ if (bs->backing_file[0]) { ++ info->inserted->has_backing_file = true; ++ info->inserted->backing_file = g_strdup(bs->backing_file); ++ } ++ ++ info->inserted->backing_file_depth = bdrv_get_backing_file_depth(bs); ++ ++ if (bs->io_limits_enabled) { ++ info->inserted->bps = ++ bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL]; ++ info->inserted->bps_rd = ++ bs->io_limits.bps[BLOCK_IO_LIMIT_READ]; ++ info->inserted->bps_wr = ++ bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE]; ++ info->inserted->iops = ++ bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL]; ++ info->inserted->iops_rd = ++ bs->io_limits.iops[BLOCK_IO_LIMIT_READ]; ++ info->inserted->iops_wr = ++ bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; ++ } ++ } ++ return info; ++} ++ ++BlockStats *bdrv_query_stats(const BlockDriverState *bs) ++{ ++ BlockStats *s; ++ ++ s = g_malloc0(sizeof(*s)); ++ ++ if (bs->device_name[0]) { ++ s->has_device = true; ++ s->device = g_strdup(bs->device_name); ++ } ++ ++ s->stats = g_malloc0(sizeof(*s->stats)); ++ s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ]; ++ s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE]; ++ s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ]; ++ s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE]; ++ s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE; ++ s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH]; ++ s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE]; ++ s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ]; ++ s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH]; ++ ++ if (bs->file) { ++ s->has_parent = true; ++ s->parent = bdrv_query_stats(bs->file); ++ } ++ ++ return s; ++} ++ ++BlockInfoList *qmp_query_block(Error **errp) ++{ ++ BlockInfoList *head = NULL, **p_next = &head; ++ BlockDriverState *bs = NULL; ++ ++ while ((bs = bdrv_next(bs))) { ++ BlockInfoList *info = g_malloc0(sizeof(*info)); ++ info->value = bdrv_query_info(bs); ++ ++ *p_next = info; ++ p_next = &info->next; ++ } ++ ++ return head; ++} ++ ++BlockStatsList *qmp_query_blockstats(Error **errp) ++{ ++ BlockStatsList *head = NULL, **p_next = &head; ++ BlockDriverState *bs = NULL; ++ ++ while ((bs = bdrv_next(bs))) { ++ BlockStatsList *info = g_malloc0(sizeof(*info)); ++ info->value = bdrv_query_stats(bs); ++ ++ *p_next = info; ++ p_next = &info->next; ++ } ++ ++ return head; ++} ++ ++#define NB_SUFFIXES 4 ++ ++static char *get_human_readable_size(char *buf, int buf_size, int64_t size) ++{ ++ static const char suffixes[NB_SUFFIXES] = "KMGT"; ++ int64_t base; ++ int i; ++ ++ if (size <= 999) { ++ snprintf(buf, buf_size, "%" PRId64, size); ++ } else { ++ base = 1024; ++ for (i = 0; i < NB_SUFFIXES; i++) { ++ if (size < (10 * base)) { ++ snprintf(buf, buf_size, "%0.1f%c", ++ (double)size / base, ++ suffixes[i]); ++ break; ++ } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { ++ snprintf(buf, buf_size, "%" PRId64 "%c", ++ ((size + (base >> 1)) / base), ++ suffixes[i]); ++ break; ++ } ++ base = base * 1024; ++ } ++ } ++ return buf; ++} ++ ++char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn) ++{ ++ char buf1[128], date_buf[128], clock_buf[128]; ++ struct tm tm; ++ time_t ti; ++ int64_t secs; ++ ++ if (!sn) { ++ snprintf(buf, buf_size, ++ "%-10s%-20s%7s%20s%15s", ++ "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK"); ++ } else { ++ ti = sn->date_sec; ++ localtime_r(&ti, &tm); ++ strftime(date_buf, sizeof(date_buf), ++ "%Y-%m-%d %H:%M:%S", &tm); ++ secs = sn->vm_clock_nsec / 1000000000; ++ snprintf(clock_buf, sizeof(clock_buf), ++ "%02d:%02d:%02d.%03d", ++ (int)(secs / 3600), ++ (int)((secs / 60) % 60), ++ (int)(secs % 60), ++ (int)((sn->vm_clock_nsec / 1000000) % 1000)); ++ snprintf(buf, buf_size, ++ "%-10s%-20s%7s%20s%15s", ++ sn->id_str, sn->name, ++ get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size), ++ date_buf, ++ clock_buf); ++ } ++ return buf; ++} ++ ++void bdrv_image_info_dump(ImageInfo *info) ++{ ++ char size_buf[128], dsize_buf[128]; ++ if (!info->has_actual_size) { ++ snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); ++ } else { ++ get_human_readable_size(dsize_buf, sizeof(dsize_buf), ++ info->actual_size); ++ } ++ get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); ++ printf("image: %s\n" ++ "file format: %s\n" ++ "virtual size: %s (%" PRId64 " bytes)\n" ++ "disk size: %s\n", ++ info->filename, info->format, size_buf, ++ info->virtual_size, ++ dsize_buf); ++ ++ if (info->has_encrypted && info->encrypted) { ++ printf("encrypted: yes\n"); ++ } ++ ++ if (info->has_cluster_size) { ++ printf("cluster_size: %" PRId64 "\n", info->cluster_size); ++ } ++ ++ if (info->has_dirty_flag && info->dirty_flag) { ++ printf("cleanly shut down: no\n"); ++ } ++ ++ if (info->has_backing_filename) { ++ printf("backing file: %s", info->backing_filename); ++ if (info->has_full_backing_filename) { ++ printf(" (actual path: %s)", info->full_backing_filename); ++ } ++ putchar('\n'); ++ if (info->has_backing_filename_format) { ++ printf("backing file format: %s\n", info->backing_filename_format); ++ } ++ } ++ ++ if (info->has_snapshots) { ++ SnapshotInfoList *elem; ++ char buf[256]; ++ ++ printf("Snapshot list:\n"); ++ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); ++ ++ /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but ++ * we convert to the block layer's native QEMUSnapshotInfo for now. ++ */ ++ for (elem = info->snapshots; elem; elem = elem->next) { ++ QEMUSnapshotInfo sn = { ++ .vm_state_size = elem->value->vm_state_size, ++ .date_sec = elem->value->date_sec, ++ .date_nsec = elem->value->date_nsec, ++ .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + ++ elem->value->vm_clock_nsec, ++ }; ++ ++ pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); ++ pstrcpy(sn.name, sizeof(sn.name), elem->value->name); ++ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn)); ++ } ++ } ++} +diff --git a/include/block/block.h b/include/block/block.h +index fac1282..7695cae 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -7,11 +7,6 @@ + #include "block/coroutine.h" + #include "qapi/qmp/qobject.h" + #include "qapi-types.h" +-/* +- * snapshot.h is needed since bdrv_snapshot_dump(), it can be removed when the +- * function is moved to other file. +- */ +-#include "block/snapshot.h" + + /* block.c */ + typedef struct BlockDriver BlockDriver; +@@ -353,12 +348,8 @@ void bdrv_get_backing_filename(BlockDriverState *bs, + char *filename, int filename_size); + void bdrv_get_full_backing_filename(BlockDriverState *bs, + char *dest, size_t sz); +-BlockInfo *bdrv_query_info(BlockDriverState *s); +-BlockStats *bdrv_query_stats(const BlockDriverState *bs); + int bdrv_is_snapshot(BlockDriverState *bs); +-char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); + +-char *get_human_readable_size(char *buf, int buf_size, int64_t size); + int path_is_absolute(const char *path); + void path_combine(char *dest, int dest_size, + const char *base_path, +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 696bbb9..9348238 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -33,6 +33,7 @@ + #include "qapi/qmp/qerror.h" + #include "monitor/monitor.h" + #include "qemu/hbitmap.h" ++#include "block/snapshot.h" + + #define BLOCK_FLAG_ENCRYPT 1 + #define BLOCK_FLAG_COMPAT6 4 +diff --git a/include/block/qapi.h b/include/block/qapi.h +new file mode 100644 +index 0000000..55d1848 +--- /dev/null ++++ b/include/block/qapi.h +@@ -0,0 +1,41 @@ ++/* ++ * Block layer qmp and info dump related functions ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef BLOCK_QAPI_H ++#define BLOCK_QAPI_H ++ ++#include "qapi-types.h" ++#include "block/block.h" ++#include "block/snapshot.h" ++ ++void bdrv_collect_snapshots(BlockDriverState *bs , ImageInfo *info); ++void bdrv_collect_image_info(BlockDriverState *bs, ++ ImageInfo *info, ++ const char *filename); ++BlockInfo *bdrv_query_info(BlockDriverState *s); ++BlockStats *bdrv_query_stats(const BlockDriverState *bs); ++ ++char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); ++void bdrv_image_info_dump(ImageInfo *info); ++#endif +diff --git a/qemu-img.c b/qemu-img.c +index 0f869f3..0bc084d 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -30,6 +30,7 @@ + #include "qemu/osdep.h" + #include "sysemu/sysemu.h" + #include "block/block_int.h" ++#include "block/qapi.h" + #include + #include + #include +@@ -1605,39 +1606,6 @@ static void dump_json_image_info_list(ImageInfoList *list) + QDECREF(str); + } + +-static void collect_snapshots(BlockDriverState *bs , ImageInfo *info) +-{ +- int i, sn_count; +- QEMUSnapshotInfo *sn_tab = NULL; +- SnapshotInfoList *info_list, *cur_item = NULL; +- sn_count = bdrv_snapshot_list(bs, &sn_tab); +- +- for (i = 0; i < sn_count; i++) { +- info->has_snapshots = true; +- info_list = g_new0(SnapshotInfoList, 1); +- +- info_list->value = g_new0(SnapshotInfo, 1); +- info_list->value->id = g_strdup(sn_tab[i].id_str); +- info_list->value->name = g_strdup(sn_tab[i].name); +- info_list->value->vm_state_size = sn_tab[i].vm_state_size; +- info_list->value->date_sec = sn_tab[i].date_sec; +- info_list->value->date_nsec = sn_tab[i].date_nsec; +- info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000; +- info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000; +- +- /* XXX: waiting for the qapi to support qemu-queue.h types */ +- if (!cur_item) { +- info->snapshots = cur_item = info_list; +- } else { +- cur_item->next = info_list; +- cur_item = info_list; +- } +- +- } +- +- g_free(sn_tab); +-} +- + static void dump_json_image_info(ImageInfo *info) + { + Error *errp = NULL; +@@ -1655,122 +1623,6 @@ static void dump_json_image_info(ImageInfo *info) + QDECREF(str); + } + +-static void collect_image_info(BlockDriverState *bs, +- ImageInfo *info, +- const char *filename, +- const char *fmt) +-{ +- uint64_t total_sectors; +- char backing_filename[1024]; +- char backing_filename2[1024]; +- BlockDriverInfo bdi; +- +- bdrv_get_geometry(bs, &total_sectors); +- +- info->filename = g_strdup(filename); +- info->format = g_strdup(bdrv_get_format_name(bs)); +- info->virtual_size = total_sectors * 512; +- info->actual_size = bdrv_get_allocated_file_size(bs); +- info->has_actual_size = info->actual_size >= 0; +- if (bdrv_is_encrypted(bs)) { +- info->encrypted = true; +- info->has_encrypted = true; +- } +- if (bdrv_get_info(bs, &bdi) >= 0) { +- if (bdi.cluster_size != 0) { +- info->cluster_size = bdi.cluster_size; +- info->has_cluster_size = true; +- } +- info->dirty_flag = bdi.is_dirty; +- info->has_dirty_flag = true; +- } +- bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); +- if (backing_filename[0] != '\0') { +- info->backing_filename = g_strdup(backing_filename); +- info->has_backing_filename = true; +- bdrv_get_full_backing_filename(bs, backing_filename2, +- sizeof(backing_filename2)); +- +- if (strcmp(backing_filename, backing_filename2) != 0) { +- info->full_backing_filename = +- g_strdup(backing_filename2); +- info->has_full_backing_filename = true; +- } +- +- if (bs->backing_format[0]) { +- info->backing_filename_format = g_strdup(bs->backing_format); +- info->has_backing_filename_format = true; +- } +- } +-} +- +-static void dump_human_image_info(ImageInfo *info) +-{ +- char size_buf[128], dsize_buf[128]; +- if (!info->has_actual_size) { +- snprintf(dsize_buf, sizeof(dsize_buf), "unavailable"); +- } else { +- get_human_readable_size(dsize_buf, sizeof(dsize_buf), +- info->actual_size); +- } +- get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size); +- printf("image: %s\n" +- "file format: %s\n" +- "virtual size: %s (%" PRId64 " bytes)\n" +- "disk size: %s\n", +- info->filename, info->format, size_buf, +- info->virtual_size, +- dsize_buf); +- +- if (info->has_encrypted && info->encrypted) { +- printf("encrypted: yes\n"); +- } +- +- if (info->has_cluster_size) { +- printf("cluster_size: %" PRId64 "\n", info->cluster_size); +- } +- +- if (info->has_dirty_flag && info->dirty_flag) { +- printf("cleanly shut down: no\n"); +- } +- +- if (info->has_backing_filename) { +- printf("backing file: %s", info->backing_filename); +- if (info->has_full_backing_filename) { +- printf(" (actual path: %s)", info->full_backing_filename); +- } +- putchar('\n'); +- if (info->has_backing_filename_format) { +- printf("backing file format: %s\n", info->backing_filename_format); +- } +- } +- +- if (info->has_snapshots) { +- SnapshotInfoList *elem; +- char buf[256]; +- +- printf("Snapshot list:\n"); +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL)); +- +- /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but +- * we convert to the block layer's native QEMUSnapshotInfo for now. +- */ +- for (elem = info->snapshots; elem; elem = elem->next) { +- QEMUSnapshotInfo sn = { +- .vm_state_size = elem->value->vm_state_size, +- .date_sec = elem->value->date_sec, +- .date_nsec = elem->value->date_nsec, +- .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL + +- elem->value->vm_clock_nsec, +- }; +- +- pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id); +- pstrcpy(sn.name, sizeof(sn.name), elem->value->name); +- printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn)); +- } +- } +-} +- + static void dump_human_image_info_list(ImageInfoList *list) + { + ImageInfoList *elem; +@@ -1782,7 +1634,7 @@ static void dump_human_image_info_list(ImageInfoList *list) + } + delim = true; + +- dump_human_image_info(elem->value); ++ bdrv_image_info_dump(elem->value); + } + } + +@@ -1832,8 +1684,8 @@ static ImageInfoList *collect_image_info_list(const char *filename, + } + + info = g_new0(ImageInfo, 1); +- collect_image_info(bs, info, filename, fmt); +- collect_snapshots(bs, info); ++ bdrv_collect_image_info(bs, info, filename); ++ bdrv_collect_snapshots(bs, info); + + elem = g_new0(ImageInfoList, 1); + elem->value = info; +diff --git a/savevm.c b/savevm.c +index 005bf35..f126bff 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -41,6 +41,7 @@ + #include "qemu/bitops.h" + #include "qemu/iov.h" + #include "block/snapshot.h" ++#include "block/qapi.h" + + #define SELF_ANNOUNCE_ROUNDS 5 + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-move-snapshot-code-in-block.c-to-block-snapsho.patch b/SOURCES/kvm-block-move-snapshot-code-in-block.c-to-block-snapsho.patch new file mode 100644 index 0000000..664aad6 --- /dev/null +++ b/SOURCES/kvm-block-move-snapshot-code-in-block.c-to-block-snapsho.patch @@ -0,0 +1,499 @@ +From 94c066bcc75fa2e57d1bc861a7a65f21891425fe Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:53 +0100 +Subject: [PATCH 02/87] block: move snapshot code in block.c to block/snapshot.c + +RH-Author: Max Reitz +Message-id: <1383604354-12743-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 55302 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 02/43] block: move snapshot code in block.c to block/snapshot.c +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Wenchao Xia + +BZ: 1026524 + +All snapshot related code, except bdrv_snapshot_dump() and +bdrv_is_snapshot(), is moved to block/snapshot.c. bdrv_snapshot_dump() +will be moved to another file later. bdrv_is_snapshot() is not related +with internal snapshot. It also fixes small code style errors reported +by check script. + +Signed-off-by: Wenchao Xia +Signed-off-by: Kevin Wolf +(cherry picked from commit de08c606f9ddafe647b6843e2b10a6d6030b0fc0) + +Signed-off-by: Max Reitz +--- + block.c | 100 ------------------------------ + block/Makefile.objs | 1 + + block/snapshot.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ + include/block/block.h | 26 ++------ + include/block/snapshot.h | 53 ++++++++++++++++ + savevm.c | 23 +------ + 6 files changed, 217 insertions(+), 143 deletions(-) + create mode 100644 block/snapshot.c + create mode 100644 include/block/snapshot.h + +Signed-off-by: Miroslav Rezanina +--- + block.c | 100 ----------------------------- + block/Makefile.objs | 1 + + block/snapshot.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++ + include/block/block.h | 26 ++------ + include/block/snapshot.h | 53 ++++++++++++++++ + savevm.c | 23 +------- + 6 files changed, 217 insertions(+), 143 deletions(-) + create mode 100644 block/snapshot.c + create mode 100644 include/block/snapshot.h + +diff --git a/block.c b/block.c +index 84a3a8d..69b70d0 100644 +--- a/block.c ++++ b/block.c +@@ -3458,111 +3458,11 @@ bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag) + return false; + } + +-/**************************************************************/ +-/* handling of snapshots */ +- +-int bdrv_can_snapshot(BlockDriverState *bs) +-{ +- BlockDriver *drv = bs->drv; +- if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { +- return 0; +- } +- +- if (!drv->bdrv_snapshot_create) { +- if (bs->file != NULL) { +- return bdrv_can_snapshot(bs->file); +- } +- return 0; +- } +- +- return 1; +-} +- + int bdrv_is_snapshot(BlockDriverState *bs) + { + return !!(bs->open_flags & BDRV_O_SNAPSHOT); + } + +-int bdrv_snapshot_create(BlockDriverState *bs, +- QEMUSnapshotInfo *sn_info) +-{ +- BlockDriver *drv = bs->drv; +- if (!drv) +- return -ENOMEDIUM; +- if (drv->bdrv_snapshot_create) +- return drv->bdrv_snapshot_create(bs, sn_info); +- if (bs->file) +- return bdrv_snapshot_create(bs->file, sn_info); +- return -ENOTSUP; +-} +- +-int bdrv_snapshot_goto(BlockDriverState *bs, +- const char *snapshot_id) +-{ +- BlockDriver *drv = bs->drv; +- int ret, open_ret; +- +- if (!drv) +- return -ENOMEDIUM; +- if (drv->bdrv_snapshot_goto) +- return drv->bdrv_snapshot_goto(bs, snapshot_id); +- +- if (bs->file) { +- drv->bdrv_close(bs); +- ret = bdrv_snapshot_goto(bs->file, snapshot_id); +- open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); +- if (open_ret < 0) { +- bdrv_delete(bs->file); +- bs->drv = NULL; +- return open_ret; +- } +- return ret; +- } +- +- return -ENOTSUP; +-} +- +-int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) +-{ +- BlockDriver *drv = bs->drv; +- if (!drv) +- return -ENOMEDIUM; +- if (drv->bdrv_snapshot_delete) +- return drv->bdrv_snapshot_delete(bs, snapshot_id); +- if (bs->file) +- return bdrv_snapshot_delete(bs->file, snapshot_id); +- return -ENOTSUP; +-} +- +-int bdrv_snapshot_list(BlockDriverState *bs, +- QEMUSnapshotInfo **psn_info) +-{ +- BlockDriver *drv = bs->drv; +- if (!drv) +- return -ENOMEDIUM; +- if (drv->bdrv_snapshot_list) +- return drv->bdrv_snapshot_list(bs, psn_info); +- if (bs->file) +- return bdrv_snapshot_list(bs->file, psn_info); +- return -ENOTSUP; +-} +- +-int bdrv_snapshot_load_tmp(BlockDriverState *bs, +- const char *snapshot_name) +-{ +- BlockDriver *drv = bs->drv; +- if (!drv) { +- return -ENOMEDIUM; +- } +- if (!bs->read_only) { +- return -EINVAL; +- } +- if (drv->bdrv_snapshot_load_tmp) { +- return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); +- } +- return -ENOTSUP; +-} +- + /* backing_file can either be relative, or absolute, or a protocol. If it is + * relative, it must be relative to the chain. So, passing in bs->filename + * from a BDS as backing_file should not be done, as that may be relative to +diff --git a/block/Makefile.objs b/block/Makefile.objs +index 41a284b..162f270 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -4,6 +4,7 @@ block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o + block-obj-y += qed-check.o + block-obj-y += vhdx.o + block-obj-y += parallels.o blkdebug.o blkverify.o ++block-obj-y += snapshot.o + block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o + block-obj-$(CONFIG_POSIX) += raw-posix.o + block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o +diff --git a/block/snapshot.c b/block/snapshot.c +new file mode 100644 +index 0000000..6c6d9de +--- /dev/null ++++ b/block/snapshot.c +@@ -0,0 +1,157 @@ ++/* ++ * Block layer snapshot related functions ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "block/snapshot.h" ++#include "block/block_int.h" ++ ++int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, ++ const char *name) ++{ ++ QEMUSnapshotInfo *sn_tab, *sn; ++ int nb_sns, i, ret; ++ ++ ret = -ENOENT; ++ nb_sns = bdrv_snapshot_list(bs, &sn_tab); ++ if (nb_sns < 0) { ++ return ret; ++ } ++ for (i = 0; i < nb_sns; i++) { ++ sn = &sn_tab[i]; ++ if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) { ++ *sn_info = *sn; ++ ret = 0; ++ break; ++ } ++ } ++ g_free(sn_tab); ++ return ret; ++} ++ ++int bdrv_can_snapshot(BlockDriverState *bs) ++{ ++ BlockDriver *drv = bs->drv; ++ if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { ++ return 0; ++ } ++ ++ if (!drv->bdrv_snapshot_create) { ++ if (bs->file != NULL) { ++ return bdrv_can_snapshot(bs->file); ++ } ++ return 0; ++ } ++ ++ return 1; ++} ++ ++int bdrv_snapshot_create(BlockDriverState *bs, ++ QEMUSnapshotInfo *sn_info) ++{ ++ BlockDriver *drv = bs->drv; ++ if (!drv) { ++ return -ENOMEDIUM; ++ } ++ if (drv->bdrv_snapshot_create) { ++ return drv->bdrv_snapshot_create(bs, sn_info); ++ } ++ if (bs->file) { ++ return bdrv_snapshot_create(bs->file, sn_info); ++ } ++ return -ENOTSUP; ++} ++ ++int bdrv_snapshot_goto(BlockDriverState *bs, ++ const char *snapshot_id) ++{ ++ BlockDriver *drv = bs->drv; ++ int ret, open_ret; ++ ++ if (!drv) { ++ return -ENOMEDIUM; ++ } ++ if (drv->bdrv_snapshot_goto) { ++ return drv->bdrv_snapshot_goto(bs, snapshot_id); ++ } ++ ++ if (bs->file) { ++ drv->bdrv_close(bs); ++ ret = bdrv_snapshot_goto(bs->file, snapshot_id); ++ open_ret = drv->bdrv_open(bs, NULL, bs->open_flags); ++ if (open_ret < 0) { ++ bdrv_delete(bs->file); ++ bs->drv = NULL; ++ return open_ret; ++ } ++ return ret; ++ } ++ ++ return -ENOTSUP; ++} ++ ++int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) ++{ ++ BlockDriver *drv = bs->drv; ++ if (!drv) { ++ return -ENOMEDIUM; ++ } ++ if (drv->bdrv_snapshot_delete) { ++ return drv->bdrv_snapshot_delete(bs, snapshot_id); ++ } ++ if (bs->file) { ++ return bdrv_snapshot_delete(bs->file, snapshot_id); ++ } ++ return -ENOTSUP; ++} ++ ++int bdrv_snapshot_list(BlockDriverState *bs, ++ QEMUSnapshotInfo **psn_info) ++{ ++ BlockDriver *drv = bs->drv; ++ if (!drv) { ++ return -ENOMEDIUM; ++ } ++ if (drv->bdrv_snapshot_list) { ++ return drv->bdrv_snapshot_list(bs, psn_info); ++ } ++ if (bs->file) { ++ return bdrv_snapshot_list(bs->file, psn_info); ++ } ++ return -ENOTSUP; ++} ++ ++int bdrv_snapshot_load_tmp(BlockDriverState *bs, ++ const char *snapshot_name) ++{ ++ BlockDriver *drv = bs->drv; ++ if (!drv) { ++ return -ENOMEDIUM; ++ } ++ if (!bs->read_only) { ++ return -EINVAL; ++ } ++ if (drv->bdrv_snapshot_load_tmp) { ++ return drv->bdrv_snapshot_load_tmp(bs, snapshot_name); ++ } ++ return -ENOTSUP; ++} +diff --git a/include/block/block.h b/include/block/block.h +index 3b3f40e..03ebc47 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -7,6 +7,11 @@ + #include "block/coroutine.h" + #include "qapi/qmp/qobject.h" + #include "qapi-types.h" ++/* ++ * snapshot.h is needed since bdrv_snapshot_dump(), it can be removed when the ++ * function is moved to other file. ++ */ ++#include "block/snapshot.h" + + /* block.c */ + typedef struct BlockDriver BlockDriver; +@@ -27,17 +32,6 @@ typedef struct BlockFragInfo { + uint64_t compressed_clusters; + } BlockFragInfo; + +-typedef struct QEMUSnapshotInfo { +- char id_str[128]; /* unique snapshot id */ +- /* the following fields are informative. They are not needed for +- the consistency of the snapshot */ +- char name[256]; /* user chosen name */ +- uint64_t vm_state_size; /* VM state info size */ +- uint32_t date_sec; /* UTC date of the snapshot */ +- uint32_t date_nsec; +- uint64_t vm_clock_nsec; /* VM clock relative to boot */ +-} QEMUSnapshotInfo; +- + /* Callbacks for block device models */ + typedef struct BlockDevOps { + /* +@@ -360,17 +354,7 @@ void bdrv_get_full_backing_filename(BlockDriverState *bs, + char *dest, size_t sz); + BlockInfo *bdrv_query_info(BlockDriverState *s); + BlockStats *bdrv_query_stats(const BlockDriverState *bs); +-int bdrv_can_snapshot(BlockDriverState *bs); + int bdrv_is_snapshot(BlockDriverState *bs); +-int bdrv_snapshot_create(BlockDriverState *bs, +- QEMUSnapshotInfo *sn_info); +-int bdrv_snapshot_goto(BlockDriverState *bs, +- const char *snapshot_id); +-int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); +-int bdrv_snapshot_list(BlockDriverState *bs, +- QEMUSnapshotInfo **psn_info); +-int bdrv_snapshot_load_tmp(BlockDriverState *bs, +- const char *snapshot_name); + char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn); + + char *get_human_readable_size(char *buf, int buf_size, int64_t size); +diff --git a/include/block/snapshot.h b/include/block/snapshot.h +new file mode 100644 +index 0000000..eaf61f0 +--- /dev/null ++++ b/include/block/snapshot.h +@@ -0,0 +1,53 @@ ++/* ++ * Block layer snapshot related functions ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef SNAPSHOT_H ++#define SNAPSHOT_H ++ ++#include "qemu-common.h" ++ ++typedef struct QEMUSnapshotInfo { ++ char id_str[128]; /* unique snapshot id */ ++ /* the following fields are informative. They are not needed for ++ the consistency of the snapshot */ ++ char name[256]; /* user chosen name */ ++ uint64_t vm_state_size; /* VM state info size */ ++ uint32_t date_sec; /* UTC date of the snapshot */ ++ uint32_t date_nsec; ++ uint64_t vm_clock_nsec; /* VM clock relative to boot */ ++} QEMUSnapshotInfo; ++ ++int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, ++ const char *name); ++int bdrv_can_snapshot(BlockDriverState *bs); ++int bdrv_snapshot_create(BlockDriverState *bs, ++ QEMUSnapshotInfo *sn_info); ++int bdrv_snapshot_goto(BlockDriverState *bs, ++ const char *snapshot_id); ++int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id); ++int bdrv_snapshot_list(BlockDriverState *bs, ++ QEMUSnapshotInfo **psn_info); ++int bdrv_snapshot_load_tmp(BlockDriverState *bs, ++ const char *snapshot_name); ++#endif +diff --git a/savevm.c b/savevm.c +index d9f3787..005bf35 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -40,6 +40,7 @@ + #include "trace.h" + #include "qemu/bitops.h" + #include "qemu/iov.h" ++#include "block/snapshot.h" + + #define SELF_ANNOUNCE_ROUNDS 5 + +@@ -2273,28 +2274,6 @@ static BlockDriverState *find_vmstate_bs(void) + return NULL; + } + +-static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, +- const char *name) +-{ +- QEMUSnapshotInfo *sn_tab, *sn; +- int nb_sns, i, ret; +- +- ret = -ENOENT; +- nb_sns = bdrv_snapshot_list(bs, &sn_tab); +- if (nb_sns < 0) +- return ret; +- for(i = 0; i < nb_sns; i++) { +- sn = &sn_tab[i]; +- if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) { +- *sn_info = *sn; +- ret = 0; +- break; +- } +- } +- g_free(sn_tab); +- return ret; +-} +- + /* + * Deletes snapshots of a given name in all opened images. + */ +-- +1.7.1 + diff --git a/SOURCES/kvm-block-optionally-disable-live-block-jobs.patch b/SOURCES/kvm-block-optionally-disable-live-block-jobs.patch new file mode 100644 index 0000000..564013a --- /dev/null +++ b/SOURCES/kvm-block-optionally-disable-live-block-jobs.patch @@ -0,0 +1,441 @@ +From 6270aec1271880bb5f12db46d40f51671c548f59 Mon Sep 17 00:00:00 2001 +From: Jeff Cody +Date: Thu, 7 Nov 2013 07:28:56 +0100 +Subject: [PATCH 57/81] block: optionally disable live block jobs + +RH-Author: Jeff Cody +Message-id: <5b15ff37a1f28a76e2b66c07df996d3a7c37d6e9.1383712781.git.jcody@redhat.com> +Patchwork-id: 55478 +O-Subject: [RHEL7 qemu-kvm PATCH 1/3] block: optionally disable live block jobs +Bugzilla: 987582 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Eric Blake +RH-Acked-by: Kevin Wolf + +This disables all block job operations that are part of the virt +differentiation features. + +This includes: + * live snapshots (single and group) + * block stream + * block commit + * block mirror + * block transactions + +All of these are disabled via the CONFIG_LIVE_BLOCK_OPS config option. + +In RHEL6, block job differentiation grew from live snapshot disablement, +which was used to encompass many operations that were not live +snapshots. CONFIG_LIVE_SNAPSHOTS was used for disablement of multiple +features. + +For RHEL7, let's use naming that is more accurate: +CONFIG_LIVE_BLOCK_OPS, to denote live block operations. + +RHEL and RHEV have different binaries, where RHEV qemu-kvm binaries +support live snapshots. + +The JSON files qapi-schema-rhel.json and qapi-schema-rhev.json are +automatically generated from the qapi-schema.json, by looking for +'_rhev_only' comments in the 'master' JSON file. + +For RHEL6, the JSON file had makeshift 'ifdef' statements. This was +changed to '_rhev_only' and '_end_rhev-only' blocks, because calling +them 'ifdef' was misleading - it did not depend on the actual state +of that variable itself. + +The Makefile variable RHEV_CONFIGS can be appended with additional +config items that may appear in the qapi-schema.json file. For +instance, to have features CONFIG_LIVE_BLOCK_OPS and CONFIG_SOME_FEATURE +both be RHEV only, set the variable like so: + +RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS CONFIG_SOME_FEATURE + +RHEV_CONFIGS is then turned into a regex. For the example above, the +following pattern is matched when generating the RHEL/RHEV JSON files: +^#_rhev-only +(\bCONFIG_LIVE_BLOCK_OPS\b|\bCONFIG_SOME_FEATURE\b) + +Unlike the RHEL6 counterpart, this one uses original qmp-commands.h, +qapi-types.h, qapi-visit.c, etc.. filenames, simplifying the Makefile a +bit. + +BZ: 987582 + +The Makefile changes were derived from +RHEL6 commit bb5bd75dd86a6d05c9df4c2d271f98744d6c90b7, but this was not +a cherry-pick as the actual changes differed significantly. + +Signed-off-by: Jeff Cody +Signed-off-by: Miroslav Rezanina +--- + Makefile | 48 ++++++++++++++++++++++++++++++++++++++++++------ + block/Makefile.objs | 2 ++ + blockdev.c | 7 +++++++ + configure | 14 +++++++++++++- + hmp-commands.hx | 5 ++++- + hmp.c | 4 ++++ + qapi-schema.json | 6 ++++++ + qmp-commands.hx | 4 ++++ + 8 files changed, 82 insertions(+), 8 deletions(-) + +diff --git a/Makefile b/Makefile +index dcd31c6..45048a3 100644 +--- a/Makefile ++++ b/Makefile +@@ -2,6 +2,11 @@ + + # Always point to the root of the build tree (needs GNU make). + BUILD_DIR=$(CURDIR) ++# useful for passing ' ' and ',' into Makefile functional calls, ++# as these characters cannot be passed otherwise ++_empty := ++_space := $(_empty) $(_empty) ++_comma := , + + # All following code might depend on configuration variables + ifneq ($(wildcard config-host.mak),) +@@ -213,15 +218,45 @@ qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\ + $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o qga/qapi-generated -p "qga-" < $<, " GEN $@") + ++# if there are multiple config items to be RHEV-only, simply add it to ++# RHEV_CONFIGS, like so: RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS CONFIG_SOME_FEATURE ++RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS ++# Turn $(RHEV_CONFIGS) into a regex with logical OR, and whole word matching ++RHEV_ONLY_CONFIG_ITEMS = (\b$(subst $(_space),\b|\b,$(strip $(RHEV_CONFIGS)))\b) ++ ++GENERATED_JSON_FILES = $(addprefix $(SRC_PATH)/, qapi-schema-rhel.json qapi-schema-rhev.json) ++ ++$(SRC_PATH)/qapi-schema-rhev.json: $(SRC_PATH)/qapi-schema.json ++ -@echo "# THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY" > $@ ++ -@echo "#" >> $@ ++ $(call quiet-command,sed -r "/^#_rhev-only +$(RHEV_ONLY_CONFIG_ITEMS)/d;/^#_end-rhev-only/d" $< >> $@, " GEN $@") ++ ++$(SRC_PATH)/qapi-schema-rhel.json: $(SRC_PATH)/qapi-schema.json ++ -@echo "# THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY" > $@ ++ -@echo "#" >> $@ ++ $(call quiet-command,sed -r "/^#_rhev-only +$(RHEV_ONLY_CONFIG_ITEMS)/$(_comma)/^#_end-rhev-only/d" $< >> $@, " GEN $@") ++ ++ifeq ($(CONFIG_LIVE_BLOCK_OPS),y) + qapi-types.c qapi-types.h :\ +-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) +- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") ++$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") + qapi-visit.c qapi-visit.h :\ +-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) +- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") ++$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") + qmp-commands.h qmp-marshal.c :\ +-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) +- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") ++$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") ++else ++qapi-types.c qapi-types.h :\ ++$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") ++qapi-visit.c qapi-visit.h :\ ++$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") ++qmp-commands.h qmp-marshal.c :\ ++$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") ++endif + + QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) + $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) +@@ -243,6 +278,7 @@ clean: + rm -f trace/generated-tracers-dtrace.h* + rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp) + rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp) ++ rm -f $(foreach f,$(GENERATED_JSON_FILES),$(f) $(f)-timestamp) + rm -rf qapi-generated + rm -rf qga/qapi-generated + $(MAKE) -C tests/tcg clean +diff --git a/block/Makefile.objs b/block/Makefile.objs +index 6b8d5ec..f355271 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -17,8 +17,10 @@ block-obj-$(CONFIG_GLUSTERFS) += gluster.o + block-obj-$(CONFIG_LIBSSH2) += ssh.o + endif + ++ifeq ($(CONFIG_LIVE_BLOCK_OPS),y) + common-obj-y += stream.o + common-obj-y += commit.o + common-obj-y += mirror.o ++endif + + $(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS) +diff --git a/blockdev.c b/blockdev.c +index f65aff4..6710f61 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -237,6 +237,8 @@ typedef struct { + DriveInfo *dinfo; + } DrivePutRefBH; + ++/* right now, this is only used from block_job_cb() */ ++#ifdef CONFIG_LIVE_BLOCK_OPS + static void drive_put_ref_bh(void *opaque) + { + DrivePutRefBH *s = opaque; +@@ -262,6 +264,7 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo) + s->dinfo = dinfo; + qemu_bh_schedule(s->bh); + } ++#endif + + static int parse_block_error_action(const char *buf, bool is_read) + { +@@ -806,6 +809,7 @@ void do_commit(Monitor *mon, const QDict *qdict) + } + } + ++#ifdef CONFIG_LIVE_BLOCK_OPS + static void blockdev_do_action(int kind, void *data, Error **errp) + { + BlockdevAction action; +@@ -1051,6 +1055,7 @@ exit: + g_free(states); + } + } ++#endif + + + static void eject_device(BlockDriverState *bs, int force, Error **errp) +@@ -1286,6 +1291,7 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp) + } + } + ++#ifdef CONFIG_LIVE_BLOCK_OPS + static void block_job_cb(void *opaque, int ret) + { + BlockDriverState *bs = opaque; +@@ -1547,6 +1553,7 @@ void qmp_drive_mirror(const char *device, const char *target, + */ + drive_get_ref(drive_get_by_blockdev(bs)); + } ++#endif + + static BlockJob *find_block_job(const char *device) + { +diff --git a/configure b/configure +index 4830f7e..9260d3c 100755 +--- a/configure ++++ b/configure +@@ -240,6 +240,7 @@ gtk="" + gtkabi="2.0" + tpm="no" + libssh2="" ++live_block_ops="yes" + + # parse CC options first + for opt do +@@ -927,7 +928,11 @@ for opt do + ;; + --enable-libssh2) libssh2="yes" + ;; +- *) echo "ERROR: unknown option $opt"; show_help="yes" ++ --disable-live-block-ops) live_block_ops="no" ++ ;; ++ --enable-live-block-ops) live_block_ops="yes" ++ ;; ++*) echo "ERROR: unknown option $opt"; show_help="yes" + ;; + esac + done +@@ -1195,6 +1200,8 @@ echo " --gcov=GCOV use specified gcov [$gcov_tool]" + echo " --enable-tpm enable TPM support" + echo " --disable-libssh2 disable ssh block device support" + echo " --enable-libssh2 enable ssh block device support" ++echo " --disable-live-block-ops disable live block operations support" ++echo " --enable-live-block-ops enable live block operations support" + echo "" + echo "NOTE: The object files are built at the place where configure is launched" + exit 1 +@@ -3556,6 +3563,7 @@ echo "TPM support $tpm" + echo "libssh2 support $libssh2" + echo "TPM passthrough $tpm_passthrough" + echo "QOM debugging $qom_cast_debug" ++echo "Live block operations $live_block_ops" + + if test "$sdl_too_old" = "yes"; then + echo "-> Your SDL version is too old - please upgrade to have SDL support" +@@ -3940,6 +3948,10 @@ if test "$virtio_blk_data_plane" = "yes" ; then + echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak + fi + ++if test "$live_block_ops" = "yes" ; then ++ echo "CONFIG_LIVE_BLOCK_OPS=y" >> $config_host_mak ++fi ++ + # USB host support + if test "$libusb" = "yes"; then + echo "HOST_USB=libusb legacy" >> $config_host_mak +diff --git a/hmp-commands.hx b/hmp-commands.hx +index 5cd6368..2fc2c0b 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -68,7 +68,7 @@ action to see the updated size. Resize to a lower size is supported, + but should be used with extreme caution. Note that this command only + resizes image files, it can not resize block devices like LVM volumes. + ETEXI +- ++#ifdef CONFIG_LIVE_BLOCK_OPS + { + .name = "block_stream", + .args_type = "device:B,speed:o?,base:s?", +@@ -76,6 +76,7 @@ ETEXI + .help = "copy data from a backing file into a block device", + .mhandler.cmd = hmp_block_stream, + }, ++#endif + + STEXI + @item block_stream +@@ -1024,6 +1025,7 @@ gdb. + ETEXI + #endif + ++#ifdef CONFIG_LIVE_BLOCK_OPS + { + .name = "snapshot_blkdev", + .args_type = "reuse:-n,device:B,snapshot-file:s?,format:s?", +@@ -1066,6 +1068,7 @@ STEXI + Start mirroring a block device's writes to a new destination, + using the specified target. + ETEXI ++#endif + + { + .name = "drive_add", +diff --git a/hmp.c b/hmp.c +index 3b3e7c7..29990d2 100644 +--- a/hmp.c ++++ b/hmp.c +@@ -838,6 +838,7 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict) + hmp_handle_error(mon, &errp); + } + ++#ifdef CONFIG_LIVE_BLOCK_OPS + void hmp_drive_mirror(Monitor *mon, const QDict *qdict) + { + const char *device = qdict_get_str(qdict, "device"); +@@ -889,6 +890,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) + true, mode, &errp); + hmp_handle_error(mon, &errp); + } ++#endif + + void hmp_migrate_cancel(Monitor *mon, const QDict *qdict) + { +@@ -1030,6 +1032,7 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict) + hmp_handle_error(mon, &err); + } + ++#ifdef CONFIG_LIVE_BLOCK_OPS + void hmp_block_stream(Monitor *mon, const QDict *qdict) + { + Error *error = NULL; +@@ -1043,6 +1046,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict) + + hmp_handle_error(mon, &error); + } ++#endif + + void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict) + { +diff --git a/qapi-schema.json b/qapi-schema.json +index b779458..12a360a 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -1617,6 +1617,7 @@ + ## + { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }} + ++#_rhev-only CONFIG_LIVE_BLOCK_OPS + ## + # @NewImageMode + # +@@ -1697,6 +1698,7 @@ + ## + { 'command': 'blockdev-snapshot-sync', + 'data': 'BlockdevSnapshot' } ++#_end-rhev-only + + ## + # @human-monitor-command: +@@ -1726,6 +1728,7 @@ + 'data': {'command-line': 'str', '*cpu-index': 'int'}, + 'returns': 'str' } + ++#_rhev-only CONFIG_LIVE_BLOCK_OPS + ## + # @block-commit + # +@@ -1811,6 +1814,7 @@ + '*speed': 'int', '*granularity': 'uint32', + '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', + '*on-target-error': 'BlockdevOnError' } } ++#_end-rhev-only + + ## + # @migrate_cancel +@@ -2123,6 +2127,7 @@ + 'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', + 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } } + ++#_rhev-only CONFIG_LIVE_BLOCK_OPS + ## + # @block-stream: + # +@@ -2160,6 +2165,7 @@ + { 'command': 'block-stream', + 'data': { 'device': 'str', '*base': 'str', '*speed': 'int', + '*on-error': 'BlockdevOnError' } } ++#_end-rhev-only + + ## + # @block-job-set-speed: +diff --git a/qmp-commands.hx b/qmp-commands.hx +index de5f394..e40d54d 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -904,6 +904,7 @@ Example: + + EQMP + ++#ifdef CONFIG_LIVE_BLOCK_OPS + { + .name = "block-stream", + .args_type = "device:B,base:s?,speed:o?,on-error:s?", +@@ -915,6 +916,7 @@ EQMP + .args_type = "device:B,base:s?,top:s,speed:o?", + .mhandler.cmd_new = qmp_marshal_input_block_commit, + }, ++#endif + + { + .name = "block-job-set-speed", +@@ -942,6 +944,7 @@ EQMP + .args_type = "device:B", + .mhandler.cmd_new = qmp_marshal_input_block_job_complete, + }, ++#ifdef CONFIG_LIVE_BLOCK_OPS + { + .name = "transaction", + .args_type = "actions:q", +@@ -1085,6 +1088,7 @@ Example: + <- { "return": {} } + + EQMP ++#endif + + { + .name = "balloon", +-- +1.7.1 + diff --git a/SOURCES/kvm-block-package-committing-code-in-qmp_transaction.patch b/SOURCES/kvm-block-package-committing-code-in-qmp_transaction.patch new file mode 100644 index 0000000..54eaa52 --- /dev/null +++ b/SOURCES/kvm-block-package-committing-code-in-qmp_transaction.patch @@ -0,0 +1,77 @@ +From cda3f47a339a8836037c0c88cd3cb4ac7c299211 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:54 +0200 +Subject: [PATCH 03/38] block: package committing code in qmp_transaction() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-4-git-send-email-kwolf@redhat.com> +Patchwork-id: 54190 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 03/32] block: package committing code in qmp_transaction() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Wenchao Xia + +Bugzilla: 1005818 + +The code is simply moved into a separate function. + +Signed-off-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 3b0047e86a1c215d830b1ae1da0778db4636b83a) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 19 ++++++++++++------- + 1 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 9eab803..eabb3f8 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -871,6 +871,17 @@ static void external_snapshot_prepare(BlockdevAction *action, + } + } + ++static void external_snapshot_commit(BlkTransactionStates *states) ++{ ++ /* This removes our old bs from the bdrv_states, and adds the new bs */ ++ bdrv_append(states->new_bs, states->old_bs); ++ /* We don't need (or want) to use the transactional ++ * bdrv_reopen_multiple() across all the entries at once, because we ++ * don't want to abort all of them if one of them fails the reopen */ ++ bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR, ++ NULL); ++} ++ + /* + * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail + * then we do not pivot any of the devices in the group, and abandon the +@@ -916,13 +927,7 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + /* Now we are going to do the actual pivot. Everything up to this point + * is reversible, but we are committed at this point */ + QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { +- /* This removes our old bs from the bdrv_states, and adds the new bs */ +- bdrv_append(states->new_bs, states->old_bs); +- /* We don't need (or want) to use the transactional +- * bdrv_reopen_multiple() across all the entries at once, because we +- * don't want to abort all of them if one of them fails the reopen */ +- bdrv_reopen(states->new_bs, states->new_bs->open_flags & ~BDRV_O_RDWR, +- NULL); ++ external_snapshot_commit(states); + } + + /* success */ +-- +1.7.1 + diff --git a/SOURCES/kvm-block-package-preparation-code-in-qmp_transaction.patch b/SOURCES/kvm-block-package-preparation-code-in-qmp_transaction.patch new file mode 100644 index 0000000..572eacf --- /dev/null +++ b/SOURCES/kvm-block-package-preparation-code-in-qmp_transaction.patch @@ -0,0 +1,220 @@ +From 9845ad55c470e47c0074d92611bf9fb2903ab58a Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:52 +0200 +Subject: [PATCH 01/38] block: package preparation code in qmp_transaction() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 54188 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 01/32] block: package preparation code in qmp_transaction() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Wenchao Xia + +Bugzilla: 1005818 + +The code before really committing is moved into a function. Most +code is simply moved from qmp_transaction(), except that on fail it +just returns now. Other code such as input parsing is not touched, +to make it easier in review. + +Signed-off-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 9b9877ee9f1c27588a286f591852c0b7c0548b6a) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 139 ++++++++++++++++++++++++++++++++++--------------------------- + 1 file changed, 77 insertions(+), 62 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 139 +++++++++++++++++++++++++++++++++--------------------------- + 1 files changed, 77 insertions(+), 62 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 6500c47..1bff654 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -785,6 +785,78 @@ typedef struct BlkTransactionStates { + QSIMPLEQ_ENTRY(BlkTransactionStates) entry; + } BlkTransactionStates; + ++static void external_snapshot_prepare(const char *device, ++ const char *format, ++ const char *new_image_file, ++ enum NewImageMode mode, ++ BlkTransactionStates *states, ++ Error **errp) ++{ ++ BlockDriver *proto_drv; ++ BlockDriver *drv; ++ int flags, ret; ++ Error *local_err = NULL; ++ ++ drv = bdrv_find_format(format); ++ if (!drv) { ++ error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); ++ return; ++ } ++ ++ states->old_bs = bdrv_find(device); ++ if (!states->old_bs) { ++ error_set(errp, QERR_DEVICE_NOT_FOUND, device); ++ return; ++ } ++ ++ if (!bdrv_is_inserted(states->old_bs)) { ++ error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); ++ return; ++ } ++ ++ if (bdrv_in_use(states->old_bs)) { ++ error_set(errp, QERR_DEVICE_IN_USE, device); ++ return; ++ } ++ ++ if (!bdrv_is_read_only(states->old_bs)) { ++ if (bdrv_flush(states->old_bs)) { ++ error_set(errp, QERR_IO_ERROR); ++ return; ++ } ++ } ++ ++ flags = states->old_bs->open_flags; ++ ++ proto_drv = bdrv_find_protocol(new_image_file); ++ if (!proto_drv) { ++ error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); ++ return; ++ } ++ ++ /* create new image w/backing file */ ++ if (mode != NEW_IMAGE_MODE_EXISTING) { ++ bdrv_img_create(new_image_file, format, ++ states->old_bs->filename, ++ states->old_bs->drv->format_name, ++ NULL, -1, flags, &local_err, false); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ return; ++ } ++ } ++ ++ /* We will manually add the backing_hd field to the bs later */ ++ states->new_bs = bdrv_new(""); ++ /* TODO Inherit bs->options or only take explicit options with an ++ * extended QMP command? */ ++ ret = bdrv_open(states->new_bs, new_image_file, NULL, ++ flags | BDRV_O_NO_BACKING, drv); ++ if (ret != 0) { ++ error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); ++ } ++} ++ + /* + * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail + * then we do not pivot any of the devices in the group, and abandon the +@@ -792,7 +864,6 @@ typedef struct BlkTransactionStates { + */ + void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + { +- int ret = 0; + BlockdevActionList *dev_entry = dev_list; + BlkTransactionStates *states, *next; + Error *local_err = NULL; +@@ -806,9 +877,6 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + /* We don't do anything in this loop that commits us to the snapshot */ + while (NULL != dev_entry) { + BlockdevAction *dev_info = NULL; +- BlockDriver *proto_drv; +- BlockDriver *drv; +- int flags; + enum NewImageMode mode; + const char *new_image_file; + const char *device; +@@ -831,70 +899,17 @@ void qmp_transaction(BlockdevActionList *dev_list, Error **errp) + format = dev_info->blockdev_snapshot_sync->format; + } + mode = dev_info->blockdev_snapshot_sync->mode; +- break; +- default: +- abort(); +- } +- +- drv = bdrv_find_format(format); +- if (!drv) { +- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); +- goto delete_and_fail; +- } +- +- states->old_bs = bdrv_find(device); +- if (!states->old_bs) { +- error_set(errp, QERR_DEVICE_NOT_FOUND, device); +- goto delete_and_fail; +- } +- +- if (!bdrv_is_inserted(states->old_bs)) { +- error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); +- goto delete_and_fail; +- } +- +- if (bdrv_in_use(states->old_bs)) { +- error_set(errp, QERR_DEVICE_IN_USE, device); +- goto delete_and_fail; +- } +- +- if (!bdrv_is_read_only(states->old_bs)) { +- if (bdrv_flush(states->old_bs)) { +- error_set(errp, QERR_IO_ERROR); +- goto delete_and_fail; +- } +- } +- +- flags = states->old_bs->open_flags; +- +- proto_drv = bdrv_find_protocol(new_image_file); +- if (!proto_drv) { +- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); +- goto delete_and_fail; +- } +- +- /* create new image w/backing file */ +- if (mode != NEW_IMAGE_MODE_EXISTING) { +- bdrv_img_create(new_image_file, format, +- states->old_bs->filename, +- states->old_bs->drv->format_name, +- NULL, -1, flags, &local_err, false); ++ external_snapshot_prepare(device, format, new_image_file, ++ mode, states, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + goto delete_and_fail; + } ++ break; ++ default: ++ abort(); + } + +- /* We will manually add the backing_hd field to the bs later */ +- states->new_bs = bdrv_new(""); +- /* TODO Inherit bs->options or only take explicit options with an +- * extended QMP command? */ +- ret = bdrv_open(states->new_bs, new_image_file, NULL, +- flags | BDRV_O_NO_BACKING, drv); +- if (ret != 0) { +- error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); +- goto delete_and_fail; +- } + } + + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-package-rollback-code-in-qmp_transaction.patch b/SOURCES/kvm-block-package-rollback-code-in-qmp_transaction.patch new file mode 100644 index 0000000..3f3445f --- /dev/null +++ b/SOURCES/kvm-block-package-rollback-code-in-qmp_transaction.patch @@ -0,0 +1,67 @@ +From 615e6e9c2adabbc5039e3fdbd49326eeb549f931 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:55 +0200 +Subject: [PATCH 04/38] block: package rollback code in qmp_transaction() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-5-git-send-email-kwolf@redhat.com> +Patchwork-id: 54191 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 04/32] block: package rollback code in qmp_transaction() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Wenchao Xia + +Bugzilla: 1005818 + +Signed-off-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 96b86bf72de0c6eda2799201517ef32910beb340) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 11 ++++++++--- + 1 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index eabb3f8..b040f0f 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -882,6 +882,13 @@ static void external_snapshot_commit(BlkTransactionStates *states) + NULL); + } + ++static void external_snapshot_abort(BlkTransactionStates *states) ++{ ++ if (states->new_bs) { ++ bdrv_delete(states->new_bs); ++ } ++} ++ + /* + * 'Atomic' group snapshots. The snapshots are taken as a set, and if any fail + * then we do not pivot any of the devices in the group, and abandon the +@@ -939,9 +946,7 @@ delete_and_fail: + * the original bs for all images + */ + QSIMPLEQ_FOREACH(states, &snap_bdrv_states, entry) { +- if (states->new_bs) { +- bdrv_delete(states->new_bs); +- } ++ external_snapshot_abort(states); + } + exit: + QSIMPLEQ_FOREACH_SAFE(states, &snap_bdrv_states, entry, next) { +-- +1.7.1 + diff --git a/SOURCES/kvm-block-qapi-Human-readable-ImageInfoSpecific-dump.patch b/SOURCES/kvm-block-qapi-Human-readable-ImageInfoSpecific-dump.patch new file mode 100644 index 0000000..9a7d625 --- /dev/null +++ b/SOURCES/kvm-block-qapi-Human-readable-ImageInfoSpecific-dump.patch @@ -0,0 +1,243 @@ +From 85b14be2b92e75320728a450635c80053d8cd374 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:36 +0100 +Subject: [PATCH 79/87] block/qapi: Human-readable ImageInfoSpecific dump + +RH-Author: Max Reitz +Message-id: <1383756824-6921-14-git-send-email-mreitz@redhat.com> +Patchwork-id: 55568 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 13/21] block/qapi: Human-readable ImageInfoSpecific dump +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +Add a function for generically dumping the ImageInfoSpecific information +in a human-readable format to block/qapi.c. + +Use this function in bdrv_image_info_dump and qemu-io-cmds.c:info_f to +allow qemu-img info resp. qemu-io -c info to print that format specific +information. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit a8d8ecb77fc16da49ea2c1edae267dc9d0c01dfd) + +Signed-off-by: Max Reitz + +Conflicts: + qemu-io.c + qemu-io-cmds.c + +Conflicts because 797ac58cb2093ab9192d8998a1fef85d87cc8661 has not been +backported, which splits qemu-io-cmds.c from qemu-io.c. +--- + block/qapi.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ + include/block/qapi.h | 2 + + qemu-io.c | 9 ++++ + 3 files changed, 132 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qapi.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ + include/block/qapi.h | 2 + + qemu-io.c | 9 ++++ + 3 files changed, 132 insertions(+), 0 deletions(-) + +diff --git a/block/qapi.c b/block/qapi.c +index 896cd37..87423fb 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -25,6 +25,9 @@ + #include "block/qapi.h" + #include "block/block_int.h" + #include "qmp-commands.h" ++#include "qapi-visit.h" ++#include "qapi/qmp-output-visitor.h" ++#include "qapi/qmp/types.h" + + /* + * Returns 0 on success, with *p_list either set to describe snapshot +@@ -400,6 +403,119 @@ void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, + } + } + ++static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation, ++ QDict *dict); ++static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation, ++ QList *list); ++ ++static void dump_qobject(fprintf_function func_fprintf, void *f, ++ int comp_indent, QObject *obj) ++{ ++ switch (qobject_type(obj)) { ++ case QTYPE_QINT: { ++ QInt *value = qobject_to_qint(obj); ++ func_fprintf(f, "%" PRId64, qint_get_int(value)); ++ break; ++ } ++ case QTYPE_QSTRING: { ++ QString *value = qobject_to_qstring(obj); ++ func_fprintf(f, "%s", qstring_get_str(value)); ++ break; ++ } ++ case QTYPE_QDICT: { ++ QDict *value = qobject_to_qdict(obj); ++ dump_qdict(func_fprintf, f, comp_indent, value); ++ break; ++ } ++ case QTYPE_QLIST: { ++ QList *value = qobject_to_qlist(obj); ++ dump_qlist(func_fprintf, f, comp_indent, value); ++ break; ++ } ++ case QTYPE_QFLOAT: { ++ QFloat *value = qobject_to_qfloat(obj); ++ func_fprintf(f, "%g", qfloat_get_double(value)); ++ break; ++ } ++ case QTYPE_QBOOL: { ++ QBool *value = qobject_to_qbool(obj); ++ func_fprintf(f, "%s", qbool_get_int(value) ? "true" : "false"); ++ break; ++ } ++ case QTYPE_QERROR: { ++ QString *value = qerror_human((QError *)obj); ++ func_fprintf(f, "%s", qstring_get_str(value)); ++ break; ++ } ++ case QTYPE_NONE: ++ break; ++ case QTYPE_MAX: ++ default: ++ abort(); ++ } ++} ++ ++static void dump_qlist(fprintf_function func_fprintf, void *f, int indentation, ++ QList *list) ++{ ++ const QListEntry *entry; ++ int i = 0; ++ ++ for (entry = qlist_first(list); entry; entry = qlist_next(entry), i++) { ++ qtype_code type = qobject_type(entry->value); ++ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); ++ const char *format = composite ? "%*s[%i]:\n" : "%*s[%i]: "; ++ ++ func_fprintf(f, format, indentation * 4, "", i); ++ dump_qobject(func_fprintf, f, indentation + 1, entry->value); ++ if (!composite) { ++ func_fprintf(f, "\n"); ++ } ++ } ++} ++ ++static void dump_qdict(fprintf_function func_fprintf, void *f, int indentation, ++ QDict *dict) ++{ ++ const QDictEntry *entry; ++ ++ for (entry = qdict_first(dict); entry; entry = qdict_next(dict, entry)) { ++ qtype_code type = qobject_type(entry->value); ++ bool composite = (type == QTYPE_QDICT || type == QTYPE_QLIST); ++ const char *format = composite ? "%*s%s:\n" : "%*s%s: "; ++ char key[strlen(entry->key) + 1]; ++ int i; ++ ++ /* replace dashes with spaces in key (variable) names */ ++ for (i = 0; entry->key[i]; i++) { ++ key[i] = entry->key[i] == '-' ? ' ' : entry->key[i]; ++ } ++ key[i] = 0; ++ ++ func_fprintf(f, format, indentation * 4, "", key); ++ dump_qobject(func_fprintf, f, indentation + 1, entry->value); ++ if (!composite) { ++ func_fprintf(f, "\n"); ++ } ++ } ++} ++ ++void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, ++ ImageInfoSpecific *info_spec) ++{ ++ Error *local_err = NULL; ++ QmpOutputVisitor *ov = qmp_output_visitor_new(); ++ QObject *obj, *data; ++ ++ visit_type_ImageInfoSpecific(qmp_output_get_visitor(ov), &info_spec, NULL, ++ &local_err); ++ obj = qmp_output_get_qobject(ov); ++ assert(qobject_type(obj) == QTYPE_QDICT); ++ data = qdict_get(qobject_to_qdict(obj), "data"); ++ dump_qobject(func_fprintf, f, 1, data); ++ qmp_output_visitor_cleanup(ov); ++} ++ + void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, + ImageInfo *info) + { +@@ -470,4 +586,9 @@ void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, + func_fprintf(f, "\n"); + } + } ++ ++ if (info->has_format_specific) { ++ func_fprintf(f, "Format specific information:\n"); ++ bdrv_image_info_specific_dump(func_fprintf, f, info->format_specific); ++ } + } +diff --git a/include/block/qapi.h b/include/block/qapi.h +index 0496cc9..9518ee4 100644 +--- a/include/block/qapi.h ++++ b/include/block/qapi.h +@@ -42,6 +42,8 @@ BlockStats *bdrv_query_stats(const BlockDriverState *bs); + + void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, + QEMUSnapshotInfo *sn); ++void bdrv_image_info_specific_dump(fprintf_function func_fprintf, void *f, ++ ImageInfoSpecific *info_spec); + void bdrv_image_info_dump(fprintf_function func_fprintf, void *f, + ImageInfo *info); + #endif +diff --git a/qemu-io.c b/qemu-io.c +index 116bb1b..df21022 100644 +--- a/qemu-io.c ++++ b/qemu-io.c +@@ -17,6 +17,7 @@ + #include "qemu-common.h" + #include "qemu/main-loop.h" + #include "block/block_int.h" ++#include "block/qapi.h" + #include "cmd.h" + #include "trace/control.h" + +@@ -1462,6 +1463,7 @@ static const cmdinfo_t length_cmd = { + static int info_f(int argc, char **argv) + { + BlockDriverInfo bdi; ++ ImageInfoSpecific *spec_info; + char s1[64], s2[64]; + int ret; + +@@ -1483,6 +1485,13 @@ static int info_f(int argc, char **argv) + printf("cluster size: %s\n", s1); + printf("vm state offset: %s\n", s2); + ++ spec_info = bdrv_get_specific_info(bs); ++ if (spec_info) { ++ printf("Format specific information:\n"); ++ bdrv_image_info_specific_dump(fprintf, stdout, spec_info); ++ qapi_free_ImageInfoSpecific(spec_info); ++ } ++ + return 0; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-raw-Employ-error-parameter.patch b/SOURCES/kvm-block-raw-Employ-error-parameter.patch new file mode 100644 index 0000000..821da0e --- /dev/null +++ b/SOURCES/kvm-block-raw-Employ-error-parameter.patch @@ -0,0 +1,51 @@ +From 5332d8432cf1a751cb60793ba8e80e7540dce9c0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:16 +0100 +Subject: [PATCH 23/87] block/raw: Employ error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-26-git-send-email-mreitz@redhat.com> +Patchwork-id: 55325 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 25/43] block/raw: Employ error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Propagate errors in raw_create rather than directly reporting and +afterwards discarding them. + +This downstream-only commit replaces upstream +92f1deec317230575726a8e0ab5c110781d30ec0 (which did the same for +raw_bsd.c instead of raw.c). + +Signed-off-by: Max Reitz +--- + block/raw.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/block/raw.c b/block/raw.c +index 50073b6..66eda91 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -113,8 +113,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, + + ret = bdrv_create_file(filename, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + } + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-raw-add-bdrv_co_write_zeroes.patch b/SOURCES/kvm-block-raw-add-bdrv_co_write_zeroes.patch new file mode 100644 index 0000000..b2244ee --- /dev/null +++ b/SOURCES/kvm-block-raw-add-bdrv_co_write_zeroes.patch @@ -0,0 +1,58 @@ +From 6fa5e64aabc703a4338a4e8705f6398df856009a Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:07 +0200 +Subject: [PATCH 12/25] block/raw: add bdrv_co_write_zeroes + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-3-git-send-email-owasserm@redhat.com> +Patchwork-id: 54798 +O-Subject: [RHEL7.0 qemu-kvm v2 02/10] block/raw: add bdrv_co_write_zeroes +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Peter Lieven + +Signed-off-by: Peter Lieven +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 8bf9344ad6883e6d85b69bab36d9d76e4257e9ed) +--- + block/raw.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/raw.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/block/raw.c b/block/raw.c +index ce10422..8c81de9 100644 +--- a/block/raw.c ++++ b/block/raw.c +@@ -42,6 +42,13 @@ static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs, + return bdrv_co_is_allocated(bs->file, sector_num, nb_sectors, pnum); + } + ++static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs, ++ int64_t sector_num, ++ int nb_sectors) ++{ ++ return bdrv_co_write_zeroes(bs->file, sector_num, nb_sectors); ++} ++ + static int64_t raw_getlength(BlockDriverState *bs) + { + return bdrv_getlength(bs->file); +@@ -128,6 +135,7 @@ static BlockDriver bdrv_raw = { + .bdrv_co_readv = raw_co_readv, + .bdrv_co_writev = raw_co_writev, + .bdrv_co_is_allocated = raw_co_is_allocated, ++ .bdrv_co_write_zeroes = raw_co_write_zeroes, + .bdrv_co_discard = raw_co_discard, + + .bdrv_probe = raw_probe, +-- +1.7.1 + diff --git a/SOURCES/kvm-block-raw-posix-Employ-error-parameter.patch b/SOURCES/kvm-block-raw-posix-Employ-error-parameter.patch new file mode 100644 index 0000000..94a1a93 --- /dev/null +++ b/SOURCES/kvm-block-raw-posix-Employ-error-parameter.patch @@ -0,0 +1,267 @@ +From 3b0640a90526abf547f13c2bd6b1bb98aec947bd Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:20 +0100 +Subject: [PATCH 27/87] block/raw-posix: Employ error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-30-git-send-email-mreitz@redhat.com> +Patchwork-id: 55329 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 29/43] block/raw-posix: Employ error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Make use of the error parameter in the opening and creating functions in +block/raw-posix.c. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit e428e439df4d92ac42cb913a1dd19b86155eae86) + +Signed-off-by: Max Reitz +--- + block/raw-posix.c | 72 ++++++++++++++++++++++++++++++++++++---------- + tests/qemu-iotests/051.out | 2 +- + 2 files changed, 58 insertions(+), 16 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-posix.c | 72 ++++++++++++++++++++++++++++++++++--------- + tests/qemu-iotests/051.out | 2 +- + 2 files changed, 58 insertions(+), 16 deletions(-) + +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 249bffb..74b15da 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -276,7 +276,7 @@ static QemuOptsList raw_runtime_opts = { + }; + + static int raw_open_common(BlockDriverState *bs, QDict *options, +- int bdrv_flags, int open_flags) ++ int bdrv_flags, int open_flags, Error **errp) + { + BDRVRawState *s = bs->opaque; + QemuOpts *opts; +@@ -287,8 +287,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + opts = qemu_opts_create_nofail(&raw_runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -297,6 +296,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + + ret = raw_normalize_devicepath(&filename); + if (ret != 0) { ++ error_setg_errno(errp, -ret, "Could not normalize device path"); + goto fail; + } + +@@ -310,6 +310,7 @@ 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; +@@ -318,6 +319,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) { + qemu_close(fd); + ret = -errno; ++ error_setg_errno(errp, -ret, "Could not set AIO state"); + goto fail; + } + #endif +@@ -339,9 +341,15 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVRawState *s = bs->opaque; ++ Error *local_err = NULL; ++ int ret; + + s->type = FTYPE_FILE; +- return raw_open_common(bs, options, flags, 0); ++ ret = raw_open_common(bs, options, flags, 0, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } ++ return ret; + } + + static int raw_reopen_prepare(BDRVReopenState *state, +@@ -366,6 +374,7 @@ static int raw_reopen_prepare(BDRVReopenState *state, + * valid in the 'false' condition even if aio_ctx is set, and raw_set_aio() + * won't override aio_ctx if aio_ctx is non-NULL */ + if (raw_set_aio(&s->aio_ctx, &raw_s->use_aio, state->flags)) { ++ error_setg(errp, "Could not set AIO state"); + return -1; + } + #endif +@@ -417,6 +426,7 @@ static int raw_reopen_prepare(BDRVReopenState *state, + assert(!(raw_s->open_flags & O_CREAT)); + raw_s->fd = qemu_open(state->bs->filename, raw_s->open_flags); + if (raw_s->fd == -1) { ++ error_setg_errno(errp, errno, "Could not reopen file"); + ret = -1; + } + } +@@ -1060,12 +1070,15 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, + 0644); + if (fd < 0) { + result = -errno; ++ error_setg_errno(errp, -result, "Could not create file"); + } else { + if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) { + result = -errno; ++ error_setg_errno(errp, -result, "Could not resize file"); + } + if (qemu_close(fd) != 0) { + result = -errno; ++ error_setg_errno(errp, -result, "Could not close the new file"); + } + } + return result; +@@ -1336,6 +1349,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVRawState *s = bs->opaque; ++ Error *local_err = NULL; + int ret; + const char *filename = qdict_get_str(options, "filename"); + +@@ -1379,8 +1393,11 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + } + #endif + +- ret = raw_open_common(bs, options, flags, 0); ++ ret = raw_open_common(bs, options, flags, 0, &local_err); + if (ret < 0) { ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + return ret; + } + +@@ -1388,6 +1405,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + ret = check_hdev_writable(s); + if (ret < 0) { + raw_close(bs); ++ error_setg_errno(errp, -ret, "The device is not writable"); + return ret; + } + } +@@ -1523,15 +1541,23 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options, + } + + fd = qemu_open(filename, O_WRONLY | O_BINARY); +- if (fd < 0) +- return -errno; ++ if (fd < 0) { ++ ret = -errno; ++ error_setg_errno(errp, -ret, "Could not open device"); ++ return ret; ++ } + +- if (fstat(fd, &stat_buf) < 0) ++ if (fstat(fd, &stat_buf) < 0) { + ret = -errno; +- else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) ++ error_setg_errno(errp, -ret, "Could not stat device"); ++ } else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode)) { ++ error_setg(errp, ++ "The given file is neither a block nor a character device"); + ret = -ENODEV; +- else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE) ++ } else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE) { ++ error_setg(errp, "Device is too small"); + ret = -ENOSPC; ++ } + + qemu_close(fd); + return ret; +@@ -1578,14 +1604,19 @@ static int floppy_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVRawState *s = bs->opaque; ++ Error *local_err = NULL; + int ret; + + s->type = FTYPE_FD; + + /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */ +- ret = raw_open_common(bs, options, flags, O_NONBLOCK); +- if (ret) ++ ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err); ++ if (ret) { ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + return ret; ++ } + + /* close fd so that we can reopen it as needed */ + qemu_close(s->fd); +@@ -1701,11 +1732,17 @@ static int cdrom_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { + BDRVRawState *s = bs->opaque; ++ Error *local_err = NULL; ++ int ret; + + s->type = FTYPE_CD; + + /* open will not fail even if no CD is inserted, so add O_NONBLOCK */ +- return raw_open_common(bs, options, flags, O_NONBLOCK); ++ ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } ++ return ret; + } + + static int cdrom_probe_device(const char *filename) +@@ -1809,13 +1846,18 @@ static BlockDriver bdrv_host_cdrom = { + static int cdrom_open(BlockDriverState *bs, QDict *options, int flags) + { + BDRVRawState *s = bs->opaque; ++ Error *local_err = NULL; + int ret; + + s->type = FTYPE_CD; + +- ret = raw_open_common(bs, options, flags, 0); +- if (ret) ++ ret = raw_open_common(bs, options, flags, 0, &local_err); ++ if (ret) { ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } + return ret; ++ } + + /* make sure the door isn't locked at this time */ + ioctl(s->fd, CDIOCALLOW); +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index fe0b347..54a6b3a 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -166,6 +166,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 'foo:bar': No such file or directory ++QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: Could not open file: No such file or directory + + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-block-raw-win32-Always-use-errno-in-hdev_open.patch b/SOURCES/kvm-block-raw-win32-Always-use-errno-in-hdev_open.patch new file mode 100644 index 0000000..93e8082 --- /dev/null +++ b/SOURCES/kvm-block-raw-win32-Always-use-errno-in-hdev_open.patch @@ -0,0 +1,60 @@ +From 96aa5a9a7d0dc4bb47e421168857eacbb36065a8 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:21 +0100 +Subject: [PATCH 28/87] block/raw-win32: Always use -errno in hdev_open + +RH-Author: Max Reitz +Message-id: <1383604354-12743-31-git-send-email-mreitz@redhat.com> +Patchwork-id: 55330 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 30/43] block/raw-win32: Always use -errno in hdev_open +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +On one occasion, hdev_open() returned -1 in case of an unknown error +instead of a proper -errno value. Adjust this to match the behavior of +raw_open() (in raw-win32), which is to return -EINVAL in this case. +Also, change the call to error_setg*() to match the one in raw_open() as +well. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 45d57f6e718e44e55780bcf1d09fa140dce7ec08) + +Signed-off-by: Max Reitz +--- + block/raw-win32.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-win32.c | 5 ++--- + 1 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/block/raw-win32.c b/block/raw-win32.c +index 5a60ca5..3e0251f 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -587,12 +587,11 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + int err = GetLastError(); + + if (err == ERROR_ACCESS_DENIED) { +- error_setg_errno(errp, EACCES, "Could not open device"); + ret = -EACCES; + } else { +- error_setg(errp, "Could not open device"); +- ret = -1; ++ ret = -EINVAL; + } ++ error_setg_errno(errp, -ret, "Could not open device"); + goto done; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-block-raw-win32-Employ-error-parameter.patch b/SOURCES/kvm-block-raw-win32-Employ-error-parameter.patch new file mode 100644 index 0000000..1b4ac8a --- /dev/null +++ b/SOURCES/kvm-block-raw-win32-Employ-error-parameter.patch @@ -0,0 +1,116 @@ +From 50ff46f7848a999267c7f15dac727fe690dabfd7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:17 +0100 +Subject: [PATCH 24/87] block/raw-win32: Employ error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-27-git-send-email-mreitz@redhat.com> +Patchwork-id: 55326 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 26/43] block/raw-win32: Employ error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Make use of the error parameter in the opening and creating functions in +block/raw-win32.c. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit c6252b7cea0dfa893cf1f49de3a58f222e910783) + +Signed-off-by: Max Reitz +--- + block/raw-win32.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-win32.c | 16 +++++++++++----- + 1 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/block/raw-win32.c b/block/raw-win32.c +index 9ebb083..5a60ca5 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -250,8 +250,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + opts = qemu_opts_create_nofail(&raw_runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -263,6 +262,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) { + aio = win32_aio_init(); + if (aio == NULL) { ++ error_setg(errp, "Could not initialize AIO"); + ret = -EINVAL; + goto fail; + } +@@ -279,6 +279,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + } else { + ret = -EINVAL; + } ++ error_setg_errno(errp, -ret, "Could not open file"); + goto fail; + } + +@@ -286,6 +287,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, + ret = win32_aio_attach(aio, s->hfile); + if (ret < 0) { + CloseHandle(s->hfile); ++ error_setg_errno(errp, -ret, "Could not enable AIO"); + goto fail; + } + s->aio = aio; +@@ -437,8 +439,10 @@ static int raw_create(const char *filename, QEMUOptionParameter *options, + + fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + 0644); +- if (fd < 0) ++ if (fd < 0) { ++ error_setg_errno(errp, errno, "Could not create file"); + return -EIO; ++ } + set_sparse(fd); + ftruncate(fd, total_size * 512); + qemu_close(fd); +@@ -547,8 +551,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + QemuOpts *opts = qemu_opts_create_nofail(&raw_runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto done; + } +@@ -557,6 +560,7 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + + if (strstart(filename, "/dev/cdrom", NULL)) { + if (find_cdrom(device_name, sizeof(device_name)) < 0) { ++ error_setg(errp, "Could not open CD-ROM drive"); + ret = -ENOENT; + goto done; + } +@@ -583,8 +587,10 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags, + int err = GetLastError(); + + if (err == ERROR_ACCESS_DENIED) { ++ error_setg_errno(errp, EACCES, "Could not open device"); + ret = -EACCES; + } else { ++ error_setg(errp, "Could not open device"); + ret = -1; + } + goto done; +-- +1.7.1 + diff --git a/SOURCES/kvm-block-remove-bdrv_is_allocated_above-bdrv_co_is_allo.patch b/SOURCES/kvm-block-remove-bdrv_is_allocated_above-bdrv_co_is_allo.patch new file mode 100644 index 0000000..0b3bd78 --- /dev/null +++ b/SOURCES/kvm-block-remove-bdrv_is_allocated_above-bdrv_co_is_allo.patch @@ -0,0 +1,166 @@ +From 6a307262a0a30089eff547a9e6489ae8fd9d242d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:32 +0200 +Subject: [PATCH 07/81] block: remove bdrv_is_allocated_above/bdrv_co_is_allocated_above distinction + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-8-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54990 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 07/26] block: remove bdrv_is_allocated_above/bdrv_co_is_allocated_above distinction +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Now that bdrv_is_allocated detects coroutine context, the two can +use the same code. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4f5786376e41980e78af45a123c56ebdc5295099) +--- + block.c | 46 ++++------------------------------------------ + block/commit.c | 6 +++--- + block/mirror.c | 4 ++-- + block/stream.c | 4 ++-- + include/block/block.h | 4 ---- + 5 files changed, 11 insertions(+), 53 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 46 ++++------------------------------------------ + block/commit.c | 6 +++--- + block/mirror.c | 4 ++-- + block/stream.c | 4 ++-- + include/block/block.h | 4 ---- + 5 files changed, 11 insertions(+), 53 deletions(-) + +diff --git a/block.c b/block.c +index 9ea8221..46d9420 100644 +--- a/block.c ++++ b/block.c +@@ -3110,10 +3110,10 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + * allocated/unallocated state. + * + */ +-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, +- BlockDriverState *base, +- int64_t sector_num, +- int nb_sectors, int *pnum) ++int bdrv_is_allocated_above(BlockDriverState *top, ++ BlockDriverState *base, ++ int64_t sector_num, ++ int nb_sectors, int *pnum) + { + BlockDriverState *intermediate; + int ret, n = nb_sectors; +@@ -3149,44 +3149,6 @@ int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, + return 0; + } + +-/* Coroutine wrapper for bdrv_is_allocated_above() */ +-static void coroutine_fn bdrv_is_allocated_above_co_entry(void *opaque) +-{ +- BdrvCoIsAllocatedData *data = opaque; +- BlockDriverState *top = data->bs; +- BlockDriverState *base = data->base; +- +- data->ret = bdrv_co_is_allocated_above(top, base, data->sector_num, +- data->nb_sectors, data->pnum); +- data->done = true; +-} +- +-/* +- * Synchronous wrapper around bdrv_co_is_allocated_above(). +- * +- * See bdrv_co_is_allocated_above() for details. +- */ +-int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base, +- int64_t sector_num, int nb_sectors, int *pnum) +-{ +- Coroutine *co; +- BdrvCoIsAllocatedData data = { +- .bs = top, +- .base = base, +- .sector_num = sector_num, +- .nb_sectors = nb_sectors, +- .pnum = pnum, +- .done = false, +- }; +- +- co = qemu_coroutine_create(bdrv_is_allocated_above_co_entry); +- qemu_coroutine_enter(co, &data); +- while (!data.done) { +- qemu_aio_wait(); +- } +- return data.ret; +-} +- + BlockInfo *bdrv_query_info(BlockDriverState *bs) + { + BlockInfo *info = g_malloc0(sizeof(*info)); +diff --git a/block/commit.c b/block/commit.c +index 553447e..74c209a 100644 +--- a/block/commit.c ++++ b/block/commit.c +@@ -108,9 +108,9 @@ wait: + break; + } + /* Copy if allocated above the base */ +- ret = bdrv_co_is_allocated_above(top, base, sector_num, +- COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE, +- &n); ++ ret = bdrv_is_allocated_above(top, base, sector_num, ++ COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE, ++ &n); + copy = (ret == 1); + trace_commit_one_iteration(s, sector_num, n, ret); + if (copy) { +diff --git a/block/mirror.c b/block/mirror.c +index 1ae724f..dad1e3e 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -338,8 +338,8 @@ static void coroutine_fn mirror_run(void *opaque) + base = s->mode == MIRROR_SYNC_MODE_FULL ? NULL : bs->backing_hd; + for (sector_num = 0; sector_num < end; ) { + int64_t next = (sector_num | (sectors_per_chunk - 1)) + 1; +- ret = bdrv_co_is_allocated_above(bs, base, +- sector_num, next - sector_num, &n); ++ ret = bdrv_is_allocated_above(bs, base, ++ sector_num, next - sector_num, &n); + + if (ret < 0) { + goto immediate_exit; +diff --git a/block/stream.c b/block/stream.c +index f8efa8a..9674c31 100644 +--- a/block/stream.c ++++ b/block/stream.c +@@ -123,8 +123,8 @@ wait: + } else { + /* Copy if allocated in the intermediate images. Limit to the + * known-unallocated area [sector_num, sector_num+n). */ +- ret = bdrv_co_is_allocated_above(bs->backing_hd, base, +- sector_num, n, &n); ++ ret = bdrv_is_allocated_above(bs->backing_hd, base, ++ sector_num, n, &n); + + /* Finish early if end of backing file has been reached */ + if (ret == 0 && n == 0) { +diff --git a/include/block/block.h b/include/block/block.h +index 1932e67..ec4d4aa 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -192,10 +192,6 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, + */ + int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs, int64_t sector_num, + int nb_sectors); +-int coroutine_fn bdrv_co_is_allocated_above(BlockDriverState *top, +- BlockDriverState *base, +- int64_t sector_num, +- int nb_sectors, int *pnum); + BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs, + const char *backing_file); + int bdrv_get_backing_file_depth(BlockDriverState *bs); +-- +1.7.1 + diff --git a/SOURCES/kvm-block-return-BDRV_BLOCK_ZERO-past-end-of-backing-fil.patch b/SOURCES/kvm-block-return-BDRV_BLOCK_ZERO-past-end-of-backing-fil.patch new file mode 100644 index 0000000..cd1dafc --- /dev/null +++ b/SOURCES/kvm-block-return-BDRV_BLOCK_ZERO-past-end-of-backing-fil.patch @@ -0,0 +1,54 @@ +From 231ea3db5b4c6b9de25fa62b2e6c39ebc4987a6f Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:41 +0200 +Subject: [PATCH 16/81] block: return BDRV_BLOCK_ZERO past end of backing file + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-17-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54999 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 16/26] block: return BDRV_BLOCK_ZERO past end of backing file +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +If the sectors are unallocated and we are past the end of the +backing file, they will read as zero. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit f0ad5712d5d15ff272b9e107910be4aae468fb3d) +--- + block.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 12 ++++++++++-- + 1 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/block.c b/block.c +index 00bc3b2..36a2f24 100644 +--- a/block.c ++++ b/block.c +@@ -3068,8 +3068,16 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + return ret; + } + +- if (!(ret & BDRV_BLOCK_DATA) && bdrv_has_zero_init(bs)) { +- ret |= BDRV_BLOCK_ZERO; ++ if (!(ret & BDRV_BLOCK_DATA)) { ++ if (bdrv_has_zero_init(bs)) { ++ ret |= BDRV_BLOCK_ZERO; ++ } else { ++ BlockDriverState *bs2 = bs->backing_hd; ++ int64_t length2 = bdrv_getlength(bs2); ++ if (length2 >= 0 && sector_num >= (length2 >> BDRV_SECTOR_BITS)) { ++ ret |= BDRV_BLOCK_ZERO; ++ } ++ } + } + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-block-return-get_block_status-data-and-flags-for-for.patch b/SOURCES/kvm-block-return-get_block_status-data-and-flags-for-for.patch new file mode 100644 index 0000000..cd7a8e8 --- /dev/null +++ b/SOURCES/kvm-block-return-get_block_status-data-and-flags-for-for.patch @@ -0,0 +1,285 @@ +From 90d033044f22ff96e5fc7c409934f7318d03f103 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:39 +0200 +Subject: [PATCH 14/81] block: return get_block_status data and flags for formats + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-15-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54996 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 14/26] block: return get_block_status data and flags for formats +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4bc74be997a72922170f4f272fd5e8074a3ecc27) +--- + block/cow.c | 8 +++++++- + block/qcow.c | 9 ++++++++- + block/qcow2.c | 16 ++++++++++++++-- + block/qed.c | 35 ++++++++++++++++++++++++++++------- + block/sheepdog.c | 2 +- + block/vdi.c | 13 ++++++++++++- + block/vmdk.c | 19 ++++++++++++++++++- + block/vvfat.c | 11 ++++++----- + 8 files changed, 94 insertions(+), 19 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/cow.c | 8 +++++++- + block/qcow.c | 9 ++++++++- + block/qcow2.c | 16 ++++++++++++++-- + block/qed.c | 35 ++++++++++++++++++++++++++++------- + block/sheepdog.c | 2 +- + block/vdi.c | 13 ++++++++++++- + block/vmdk.c | 19 ++++++++++++++++++- + block/vvfat.c | 11 ++++++----- + 8 files changed, 94 insertions(+), 19 deletions(-) + +diff --git a/block/cow.c b/block/cow.c +index 5e71c76..6958808 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -191,7 +191,13 @@ static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs, + static int64_t coroutine_fn cow_co_get_block_status(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *num_same) + { +- return cow_co_is_allocated(bs, sector_num, nb_sectors, num_same); ++ BDRVCowState *s = bs->opaque; ++ int ret = cow_co_is_allocated(bs, sector_num, nb_sectors, num_same); ++ int64_t offset = s->cow_sectors_offset + (sector_num << BDRV_SECTOR_BITS); ++ if (ret < 0) { ++ return ret; ++ } ++ return (ret ? BDRV_BLOCK_DATA : 0) | offset | BDRV_BLOCK_OFFSET_VALID; + } + + static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num, +diff --git a/block/qcow.c b/block/qcow.c +index 05af25c..4ab552e 100644 +--- a/block/qcow.c ++++ b/block/qcow.c +@@ -410,7 +410,14 @@ static int64_t coroutine_fn qcow_co_get_block_status(BlockDriverState *bs, + if (n > nb_sectors) + n = nb_sectors; + *pnum = n; +- return (cluster_offset != 0); ++ if (!cluster_offset) { ++ return 0; ++ } ++ if ((cluster_offset & QCOW_OFLAG_COMPRESSED) || s->crypt_method) { ++ return BDRV_BLOCK_DATA; ++ } ++ cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS); ++ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | cluster_offset; + } + + static int decompress_buffer(uint8_t *out_buf, int out_buf_size, +diff --git a/block/qcow2.c b/block/qcow2.c +index 8d3bf5d..8e894b9 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -645,7 +645,8 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, + { + BDRVQcowState *s = bs->opaque; + uint64_t cluster_offset; +- int ret; ++ int index_in_cluster, ret; ++ int64_t status = 0; + + *pnum = nb_sectors; + qemu_co_mutex_lock(&s->lock); +@@ -655,7 +656,18 @@ static int64_t coroutine_fn qcow2_co_get_block_status(BlockDriverState *bs, + return ret; + } + +- return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO); ++ if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED && ++ !s->crypt_method) { ++ index_in_cluster = sector_num & (s->cluster_sectors - 1); ++ cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS); ++ status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset; ++ } ++ if (ret == QCOW2_CLUSTER_ZERO) { ++ status |= BDRV_BLOCK_ZERO; ++ } else if (ret != QCOW2_CLUSTER_UNALLOCATED) { ++ status |= BDRV_BLOCK_DATA; ++ } ++ return status; + } + + /* handle reading after the end of the backing file */ +diff --git a/block/qed.c b/block/qed.c +index a573039..815ee1c 100644 +--- a/block/qed.c ++++ b/block/qed.c +@@ -652,16 +652,36 @@ static int bdrv_qed_create(const char *filename, QEMUOptionParameter *options) + } + + typedef struct { ++ BlockDriverState *bs; + Coroutine *co; +- int is_allocated; ++ uint64_t pos; ++ int64_t status; + int *pnum; + } QEDIsAllocatedCB; + + static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t len) + { + QEDIsAllocatedCB *cb = opaque; ++ BDRVQEDState *s = cb->bs->opaque; + *cb->pnum = len / BDRV_SECTOR_SIZE; +- cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO); ++ switch (ret) { ++ case QED_CLUSTER_FOUND: ++ offset |= qed_offset_into_cluster(s, cb->pos); ++ cb->status = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset; ++ break; ++ case QED_CLUSTER_ZERO: ++ cb->status = BDRV_BLOCK_ZERO; ++ break; ++ case QED_CLUSTER_L2: ++ case QED_CLUSTER_L1: ++ cb->status = 0; ++ break; ++ default: ++ assert(ret < 0); ++ cb->status = ret; ++ break; ++ } ++ + if (cb->co) { + qemu_coroutine_enter(cb->co, NULL); + } +@@ -672,25 +692,26 @@ static int64_t coroutine_fn bdrv_qed_co_get_block_status(BlockDriverState *bs, + int nb_sectors, int *pnum) + { + BDRVQEDState *s = bs->opaque; +- uint64_t pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE; + size_t len = (size_t)nb_sectors * BDRV_SECTOR_SIZE; + QEDIsAllocatedCB cb = { +- .is_allocated = -1, ++ .bs = bs, ++ .pos = (uint64_t)sector_num * BDRV_SECTOR_SIZE, ++ .status = BDRV_BLOCK_OFFSET_MASK, + .pnum = pnum, + }; + QEDRequest request = { .l2_table = NULL }; + +- qed_find_cluster(s, &request, pos, len, qed_is_allocated_cb, &cb); ++ qed_find_cluster(s, &request, cb.pos, len, qed_is_allocated_cb, &cb); + + /* Now sleep if the callback wasn't invoked immediately */ +- while (cb.is_allocated == -1) { ++ while (cb.status == BDRV_BLOCK_OFFSET_MASK) { + cb.co = qemu_coroutine_self(); + qemu_coroutine_yield(); + } + + qed_unref_l2_cache_entry(request.l2_table); + +- return cb.is_allocated; ++ return cb.status; + } + + static int bdrv_qed_make_empty(BlockDriverState *bs) +diff --git a/block/sheepdog.c b/block/sheepdog.c +index e5398bb..f7cc76e 100644 +--- a/block/sheepdog.c ++++ b/block/sheepdog.c +@@ -2299,7 +2299,7 @@ sd_co_get_block_status(BlockDriverState *bs, int64_t sector_num, int nb_sectors, + end = DIV_ROUND_UP((sector_num + nb_sectors) * + BDRV_SECTOR_SIZE, SD_DATA_OBJ_SIZE); + unsigned long idx; +- int ret = 1; ++ int64_t ret = BDRV_BLOCK_DATA; + + for (idx = start; idx < end; idx++) { + if (inode->data_vdi_id[idx] == 0) { +diff --git a/block/vdi.c b/block/vdi.c +index 1252ad4..bc97c39 100644 +--- a/block/vdi.c ++++ b/block/vdi.c +@@ -479,12 +479,23 @@ static int64_t coroutine_fn vdi_co_get_block_status(BlockDriverState *bs, + size_t sector_in_block = sector_num % s->block_sectors; + int n_sectors = s->block_sectors - sector_in_block; + uint32_t bmap_entry = le32_to_cpu(s->bmap[bmap_index]); ++ uint64_t offset; ++ int result; ++ + logout("%p, %" PRId64 ", %d, %p\n", bs, sector_num, nb_sectors, pnum); + if (n_sectors > nb_sectors) { + n_sectors = nb_sectors; + } + *pnum = n_sectors; +- return VDI_IS_ALLOCATED(bmap_entry); ++ result = VDI_IS_ALLOCATED(bmap_entry); ++ if (!result) { ++ return 0; ++ } ++ ++ offset = s->header.offset_data + ++ (uint64_t)bmap_entry * s->block_size + ++ sector_in_block * SECTOR_SIZE; ++ return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | offset; + } + + static int vdi_co_read(BlockDriverState *bs, +diff --git a/block/vmdk.c b/block/vmdk.c +index a30c3b9..7456f9b 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1059,7 +1059,24 @@ static int64_t coroutine_fn vmdk_co_get_block_status(BlockDriverState *bs, + sector_num * 512, 0, &offset); + qemu_co_mutex_unlock(&s->lock); + +- ret = (ret == VMDK_OK || ret == VMDK_ZEROED); ++ switch (ret) { ++ case VMDK_ERROR: ++ ret = -EIO; ++ break; ++ case VMDK_UNALLOC: ++ ret = 0; ++ break; ++ case VMDK_ZEROED: ++ ret = BDRV_BLOCK_ZERO; ++ break; ++ case VMDK_OK: ++ ret = BDRV_BLOCK_DATA; ++ if (extent->file == bs->file) { ++ ret |= BDRV_BLOCK_OFFSET_VALID | offset; ++ } ++ ++ break; ++ } + + index_in_cluster = sector_num % extent->cluster_sectors; + n = extent->cluster_sectors - index_in_cluster; +diff --git a/block/vvfat.c b/block/vvfat.c +index 510a559..415fba3 100644 +--- a/block/vvfat.c ++++ b/block/vvfat.c +@@ -2879,11 +2879,12 @@ static int64_t coroutine_fn vvfat_co_get_block_status(BlockDriverState *bs, + { + BDRVVVFATState* s = bs->opaque; + *n = s->sector_count - sector_num; +- if (*n > nb_sectors) +- *n = nb_sectors; +- else if (*n < 0) +- return 0; +- return 1; ++ if (*n > nb_sectors) { ++ *n = nb_sectors; ++ } else if (*n < 0) { ++ return 0; ++ } ++ return BDRV_BLOCK_DATA; + } + + static int write_target_commit(BlockDriverState *bs, int64_t sector_num, +-- +1.7.1 + diff --git a/SOURCES/kvm-block-use-bdrv_has_zero_init-to-return-BDRV_BLOCK_ZE.patch b/SOURCES/kvm-block-use-bdrv_has_zero_init-to-return-BDRV_BLOCK_ZE.patch new file mode 100644 index 0000000..9a0e601 --- /dev/null +++ b/SOURCES/kvm-block-use-bdrv_has_zero_init-to-return-BDRV_BLOCK_ZE.patch @@ -0,0 +1,61 @@ +From 95dd0c697b1b924c282cad302fc7f5af3330993d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:40 +0200 +Subject: [PATCH 15/81] block: use bdrv_has_zero_init to return BDRV_BLOCK_ZERO + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-16-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54998 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 15/26] block: use bdrv_has_zero_init to return BDRV_BLOCK_ZERO +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Alternatively, this could use a "discard zeroes data" flag returned +by bdrv_get_info. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 415b5b013ce74126e71459b922a92377918ae2ef) +--- + block.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 11 ++++++++++- + 1 files changed, 10 insertions(+), 1 deletions(-) + +diff --git a/block.c b/block.c +index 8c583bf..00bc3b2 100644 +--- a/block.c ++++ b/block.c +@@ -3041,6 +3041,7 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + { + int64_t length; + int64_t n; ++ int64_t ret; + + length = bdrv_getlength(bs); + if (length < 0) { +@@ -3062,7 +3063,15 @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs, + return BDRV_BLOCK_DATA; + } + +- return bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); ++ ret = bs->drv->bdrv_co_get_block_status(bs, sector_num, nb_sectors, pnum); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (!(ret & BDRV_BLOCK_DATA) && bdrv_has_zero_init(bs)) { ++ ret |= BDRV_BLOCK_ZERO; ++ } ++ return ret; + } + + /* Coroutine wrapper for bdrv_get_block_status() */ +-- +1.7.1 + diff --git a/SOURCES/kvm-block-vhdx-add-migration-blocker.patch b/SOURCES/kvm-block-vhdx-add-migration-blocker.patch new file mode 100644 index 0000000..91ac7bb --- /dev/null +++ b/SOURCES/kvm-block-vhdx-add-migration-blocker.patch @@ -0,0 +1,75 @@ +From 7ac8b98c5873a6c69a73a2a1c03518137024efb8 Mon Sep 17 00:00:00 2001 +From: Jeffrey Cody +Date: Wed, 6 Nov 2013 19:01:09 +0100 +Subject: [PATCH 79/81] block: vhdx - add migration blocker + +RH-Author: Jeffrey Cody +Message-id: <92e2ff0b02d3cfe596589be909331fd83e66667b.1383763969.git.jcody@redhat.com> +Patchwork-id: 55578 +O-Subject: [RHEL7 qemu-kvm PATCH 1/3] block: vhdx - add migration blocker +Bugzilla: 1007176 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Max Reitz +RH-Acked-by: Alex Williamson +RH-Acked-by: Fam Zheng + +This blocks migration for VHDX image files, until the +functionality can be supported. + +Signed-off-by: Jeff Cody +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 5641bf405608cc89578fafed8ec689a19046285a) +--- + block/vhdx.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/vhdx.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/block/vhdx.c b/block/vhdx.c +index e9704b1..11d923f 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -20,6 +20,7 @@ + #include "qemu/module.h" + #include "qemu/crc32c.h" + #include "block/vhdx.h" ++#include "migration/migration.h" + + + /* Several metadata and region table data entries are identified by +@@ -159,6 +160,7 @@ typedef struct BDRVVHDXState { + VHDXParentLocatorHeader parent_header; + VHDXParentLocatorEntry *parent_entries; + ++ Error *migration_blocker; + } BDRVVHDXState; + + uint32_t vhdx_checksum_calc(uint32_t crc, uint8_t *buf, size_t size, +@@ -805,6 +807,12 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags) + + /* TODO: differencing files, write */ + ++ /* Disable migration when VHDX images are used */ ++ error_set(&s->migration_blocker, ++ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, ++ "vhdx", bs->device_name, "live migration"); ++ migrate_add_blocker(s->migration_blocker); ++ + return 0; + fail: + qemu_vfree(s->headers[0]); +@@ -951,6 +959,8 @@ static void vhdx_close(BlockDriverState *bs) + qemu_vfree(s->headers[1]); + qemu_vfree(s->bat); + qemu_vfree(s->parent_entries); ++ migrate_del_blocker(s->migration_blocker); ++ error_free(s->migration_blocker); + } + + static BlockDriver bdrv_vhdx = { +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Don-t-disable-COR-automatically-with-blockd.patch b/SOURCES/kvm-blockdev-Don-t-disable-COR-automatically-with-blockd.patch new file mode 100644 index 0000000..7b6ec5f --- /dev/null +++ b/SOURCES/kvm-blockdev-Don-t-disable-COR-automatically-with-blockd.patch @@ -0,0 +1,121 @@ +From f511f5b093b500474168bb0c7e95b1a48a0d5d42 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:13 +0100 +Subject: [PATCH 60/87] blockdev: Don't disable COR automatically with blockdev-add + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-20-git-send-email-kwolf@redhat.com> +Patchwork-id: 55398 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 19/24] blockdev: Don't disable COR automatically with blockdev-add +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +If a read-only device is configured with copy-on-read=on, the old code +only prints a warning and automatically disables copy on read. Make it +a real error for blockdev-add. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit 0ebd24e0a203cf2852c310b59fbe050190dc6c8c) + +Signed-off-by: Kevin Wolf +--- + block.c | 9 +++++++-- + blockdev.c | 31 +++++++++++++++++++++++++++---- + 2 files changed, 34 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block.c | 9 +++++++-- + blockdev.c | 31 +++++++++++++++++++++++++++---- + 2 files changed, 34 insertions(+), 6 deletions(-) + +diff --git a/block.c b/block.c +index c2b6930..d11661a 100644 +--- a/block.c ++++ b/block.c +@@ -746,8 +746,13 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, + } + + assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ +- if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) { +- bdrv_enable_copy_on_read(bs); ++ if (flags & BDRV_O_COPY_ON_READ) { ++ if (!bs->read_only) { ++ bdrv_enable_copy_on_read(bs); ++ } else { ++ error_setg(errp, "Can't use copy-on-read on read-only device"); ++ return -EINVAL; ++ } + } + + if (filename != NULL) { +diff --git a/blockdev.c b/blockdev.c +index d4b18c5..cbf01eb 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -511,10 +511,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + + bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + +- if (ro && copy_on_read) { +- error_report("warning: disabling copy_on_read on read-only drive"); +- } +- + QINCREF(bs_opts); + ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error); + +@@ -602,6 +598,18 @@ QemuOptsList qemu_legacy_drive_opts = { + .type = QEMU_OPT_STRING, + .help = "pci address (virtio only)", + }, ++ ++ /* Options that are passed on, but have special semantics with -drive */ ++ { ++ .name = "read-only", ++ .type = QEMU_OPT_BOOL, ++ .help = "open drive file as read-only", ++ },{ ++ .name = "copy-on-read", ++ .type = QEMU_OPT_BOOL, ++ .help = "copy read data from backing file into image file", ++ }, ++ + { /* end of list */ } + }, + }; +@@ -617,6 +625,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + int cyls, heads, secs, translation; + int max_devs, bus_id, unit_id, index; + const char *devaddr; ++ bool read_only, copy_on_read; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -688,6 +697,20 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + } + ++ /* copy-on-read is disabled with a warning for read-only devices */ ++ read_only = qemu_opt_get_bool(legacy_opts, "read-only", false); ++ copy_on_read = qemu_opt_get_bool(legacy_opts, "copy-on-read", false); ++ ++ if (read_only && copy_on_read) { ++ error_report("warning: disabling copy-on-read on read-only drive"); ++ copy_on_read = false; ++ } ++ ++ qdict_put(bs_opts, "read-only", ++ qstring_from_str(read_only ? "on" : "off")); ++ qdict_put(bs_opts, "copy-on-read", ++ qstring_from_str(copy_on_read ? "on" :"off")); ++ + /* Controller type */ + value = qemu_opt_get(legacy_opts, "if"); + if (value) { +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Introduce-DriveInfo.enable_auto_del.patch b/SOURCES/kvm-blockdev-Introduce-DriveInfo.enable_auto_del.patch new file mode 100644 index 0000000..f3a913e --- /dev/null +++ b/SOURCES/kvm-blockdev-Introduce-DriveInfo.enable_auto_del.patch @@ -0,0 +1,95 @@ +From 543610e2a818c44591670da35107ae8d17406382 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:08:59 +0100 +Subject: [PATCH 46/87] blockdev: Introduce DriveInfo.enable_auto_del + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-6-git-send-email-kwolf@redhat.com> +Patchwork-id: 55384 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 05/24] blockdev: Introduce DriveInfo.enable_auto_del +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +BlockDriverStates shouldn't be affected by an unplugged guest device, +except if created with the legacy -drive command line option or the +drive_add HMP command. + +Make the automatic deletion as well as cancelling of jobs conditional on +an enable_auto_del boolean that is only set in drive_init(). + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Wenchao Xia +(cherry picked from commit 2d246f01d374c1a10c48c45aa931aa18f0a56634) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 17 ++++++++++++++++- + include/sysemu/blockdev.h | 1 + + 2 files changed, 17 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 17 ++++++++++++++++- + include/sysemu/blockdev.h | 1 + + 2 files changed, 17 insertions(+), 1 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 2fb6d83..e379a91 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -89,6 +89,10 @@ void blockdev_mark_auto_del(BlockDriverState *bs) + { + DriveInfo *dinfo = drive_get_by_blockdev(bs); + ++ if (dinfo && !dinfo->enable_auto_del) { ++ return; ++ } ++ + if (bs->job) { + block_job_cancel(bs->job); + } +@@ -747,6 +751,7 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to) + DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + { + const char *value; ++ DriveInfo *dinfo; + + /* Change legacy command line options into QMP ones */ + qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); +@@ -784,7 +789,17 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + qemu_opt_unset(all_opts, "cache"); + } + +- return blockdev_init(all_opts, block_default_type); ++ /* Actual block device init: Functionality shared with blockdev-add */ ++ dinfo = blockdev_init(all_opts, block_default_type); ++ if (dinfo == NULL) { ++ goto fail; ++ } ++ ++ /* Set legacy DriveInfo fields */ ++ dinfo->enable_auto_del = true; ++ ++fail: ++ return dinfo; + } + + void do_commit(Monitor *mon, const QDict *qdict) +diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h +index 804ec88..1082091 100644 +--- a/include/sysemu/blockdev.h ++++ b/include/sysemu/blockdev.h +@@ -37,6 +37,7 @@ struct DriveInfo { + int bus; + int unit; + int auto_del; /* see blockdev_mark_auto_del() */ ++ bool enable_auto_del; /* Only for legacy drive_init() */ + int media_cd; + int cyls, heads, secs, trans; + QemuOpts *opts; +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Move-bus-unit-index-processing-to-drive_ini.patch b/SOURCES/kvm-blockdev-Move-bus-unit-index-processing-to-drive_ini.patch new file mode 100644 index 0000000..35c9d12 --- /dev/null +++ b/SOURCES/kvm-blockdev-Move-bus-unit-index-processing-to-drive_ini.patch @@ -0,0 +1,266 @@ +From 9ab9b4d966cf80520ad0864bc61b1d3a255ce39c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:08 +0100 +Subject: [PATCH 55/87] blockdev: Move bus/unit/index processing to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-15-git-send-email-kwolf@redhat.com> +Patchwork-id: 55393 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 14/24] blockdev: Move bus/unit/index processing to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +This requires moving the automatic ID generation at the same time, so +let's do that as well. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit 87a899c5090c7864fc7dcff3ea0ac34153ea621b) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 157 ++++++++++++++++++++++++++++--------------------------------- + 1 file changed, 73 insertions(+), 84 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 157 ++++++++++++++++++++++++++++-------------------------------- + 1 files changed, 73 insertions(+), 84 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 9f9cbba..b6dff50 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -334,10 +334,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + const char *buf; + const char *file = NULL; + const char *serial; +- const char *mediastr = ""; +- int bus_id, unit_id; +- int max_devs; +- int index; + int ro = 0; + int bdrv_flags = 0; + int on_read_error, on_write_error; +@@ -377,10 +373,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + has_driver_specific_opts = !!qdict_size(bs_opts); + + /* extract parameters */ +- bus_id = qemu_opt_get_number(opts, "bus", 0); +- unit_id = qemu_opt_get_number(opts, "unit", -1); +- index = qemu_opt_get_number(opts, "index", -1); +- + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); + ro = qemu_opt_get_bool(opts, "read-only", 0); + copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false); +@@ -388,8 +380,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + file = qemu_opt_get(opts, "file"); + serial = qemu_opt_get(opts, "serial"); + +- max_devs = if_max_devs[type]; +- + if ((buf = qemu_opt_get(opts, "discard")) != NULL) { + if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) { + error_report("invalid discard option"); +@@ -489,66 +479,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + } + } + +- /* compute bus and unit according index */ +- +- if (index != -1) { +- if (bus_id != 0 || unit_id != -1) { +- error_report("index cannot be used with bus and unit"); +- return NULL; +- } +- bus_id = drive_index_to_bus_id(type, index); +- unit_id = drive_index_to_unit_id(type, index); +- } +- +- /* if user doesn't specify a unit_id, +- * try to find the first free +- */ +- +- if (unit_id == -1) { +- unit_id = 0; +- while (drive_get(type, bus_id, unit_id) != NULL) { +- unit_id++; +- if (max_devs && unit_id >= max_devs) { +- unit_id -= max_devs; +- bus_id++; +- } +- } +- } +- +- /* check unit id */ +- +- if (max_devs && unit_id >= max_devs) { +- error_report("unit %d too big (max is %d)", +- unit_id, max_devs - 1); +- return NULL; +- } +- +- /* +- * catch multiple definitions +- */ +- +- if (drive_get(type, bus_id, unit_id) != NULL) { +- error_report("drive with bus=%d, unit=%d (index=%d) exists", +- bus_id, unit_id, index); +- return NULL; +- } +- +- /* no id supplied -> create one */ +- if (qemu_opts_id(opts) == NULL) { +- char *new_id; +- if (type == IF_IDE || type == IF_SCSI) { +- mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; +- } +- if (max_devs) { +- new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id, +- mediastr, unit_id); +- } else { +- new_id = g_strdup_printf("%s%s%i", if_name[type], +- mediastr, unit_id); +- } +- qemu_opts_set_id(opts, new_id); +- } +- + /* init */ + dinfo = g_malloc0(sizeof(*dinfo)); + dinfo->id = g_strdup(qemu_opts_id(opts)); +@@ -557,8 +487,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + dinfo->bdrv->read_only = ro; + dinfo->devaddr = devaddr; + dinfo->type = type; +- dinfo->bus = bus_id; +- dinfo->unit = unit_id; + dinfo->refcount = 1; + if (serial != NULL) { + dinfo->serial = g_strdup(serial); +@@ -681,6 +609,18 @@ QemuOptsList qemu_legacy_drive_opts = { + .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head), + .desc = { + { ++ .name = "bus", ++ .type = QEMU_OPT_NUMBER, ++ .help = "bus number", ++ },{ ++ .name = "unit", ++ .type = QEMU_OPT_NUMBER, ++ .help = "unit number (i.e. lun for scsi)", ++ },{ ++ .name = "index", ++ .type = QEMU_OPT_NUMBER, ++ .help = "index number", ++ },{ + .name = "media", + .type = QEMU_OPT_STRING, + .help = "media type (disk, cdrom)", +@@ -722,6 +662,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + DriveMediaType media = MEDIA_DISK; + BlockInterfaceType type; + int cyls, heads, secs, translation; ++ int max_devs, bus_id, unit_id, index; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -854,6 +795,63 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + } + ++ /* Device address specified by bus/unit or index. ++ * If none was specified, try to find the first free one. */ ++ bus_id = qemu_opt_get_number(legacy_opts, "bus", 0); ++ unit_id = qemu_opt_get_number(legacy_opts, "unit", -1); ++ index = qemu_opt_get_number(legacy_opts, "index", -1); ++ ++ max_devs = if_max_devs[type]; ++ ++ if (index != -1) { ++ if (bus_id != 0 || unit_id != -1) { ++ error_report("index cannot be used with bus and unit"); ++ goto fail; ++ } ++ bus_id = drive_index_to_bus_id(type, index); ++ unit_id = drive_index_to_unit_id(type, index); ++ } ++ ++ if (unit_id == -1) { ++ unit_id = 0; ++ while (drive_get(type, bus_id, unit_id) != NULL) { ++ unit_id++; ++ if (max_devs && unit_id >= max_devs) { ++ unit_id -= max_devs; ++ bus_id++; ++ } ++ } ++ } ++ ++ if (max_devs && unit_id >= max_devs) { ++ error_report("unit %d too big (max is %d)", unit_id, max_devs - 1); ++ goto fail; ++ } ++ ++ if (drive_get(type, bus_id, unit_id) != NULL) { ++ error_report("drive with bus=%d, unit=%d (index=%d) exists", ++ bus_id, unit_id, index); ++ goto fail; ++ } ++ ++ /* no id supplied -> create one */ ++ if (qemu_opts_id(all_opts) == NULL) { ++ char *new_id; ++ const char *mediastr = ""; ++ if (type == IF_IDE || type == IF_SCSI) { ++ mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; ++ } ++ if (max_devs) { ++ new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id, ++ mediastr, unit_id); ++ } else { ++ new_id = g_strdup_printf("%s%s%i", if_name[type], ++ mediastr, unit_id); ++ } ++ qdict_put(bs_opts, "id", qstring_from_str(new_id)); ++ g_free(new_id); ++ } ++ + /* Actual block device init: Functionality shared with blockdev-add */ + dinfo = blockdev_init(bs_opts, type, media); + if (dinfo == NULL) { +@@ -869,6 +867,9 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + dinfo->secs = secs; + dinfo->trans = translation; + ++ dinfo->bus = bus_id; ++ dinfo->unit = unit_id; ++ + fail: + qemu_opts_del(legacy_opts); + return dinfo; +@@ -1804,18 +1805,6 @@ QemuOptsList qemu_common_drive_opts = { + .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head), + .desc = { + { +- .name = "bus", +- .type = QEMU_OPT_NUMBER, +- .help = "bus number", +- },{ +- .name = "unit", +- .type = QEMU_OPT_NUMBER, +- .help = "unit number (i.e. lun for scsi)", +- },{ +- .name = "index", +- .type = QEMU_OPT_NUMBER, +- .help = "index number", +- },{ + .name = "snapshot", + .type = QEMU_OPT_BOOL, + .help = "enable/disable snapshot mode", +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Move-parsing-of-boot-option-to-drive_init.patch b/SOURCES/kvm-blockdev-Move-parsing-of-boot-option-to-drive_init.patch new file mode 100644 index 0000000..7b04e14 --- /dev/null +++ b/SOURCES/kvm-blockdev-Move-parsing-of-boot-option-to-drive_init.patch @@ -0,0 +1,87 @@ +From f57c1d76bbddfd3a12f35c59c043eaed7be44206 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:07 +0100 +Subject: [PATCH 54/87] blockdev: Move parsing of 'boot' option to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-14-git-send-email-kwolf@redhat.com> +Patchwork-id: 55392 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 13/24] blockdev: Move parsing of 'boot' option to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +It's already ignored and only prints a deprecation message. No use in +making it available in new interfaces. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 26929298023b0592dc6ac8bc15163b5a24341670) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 21 +++++++++++---------- + 1 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index d69c4a8..9f9cbba 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -456,12 +456,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + return NULL; + } + +- if (qemu_opt_get(opts, "boot") != NULL) { +- fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be " +- "ignored. Future versions will reject this parameter. Please " +- "update your scripts.\n"); +- } +- + on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { + if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { +@@ -710,6 +704,10 @@ QemuOptsList qemu_legacy_drive_opts = { + .name = "trans", + .type = QEMU_OPT_STRING, + .help = "chs translation (auto, lba, none)", ++ },{ ++ .name = "boot", ++ .type = QEMU_OPT_BOOL, ++ .help = "(deprecated, ignored)", + }, + { /* end of list */ } + }, +@@ -774,6 +772,13 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + goto fail; + } + ++ /* Deprecated option boot=[on|off] */ ++ if (qemu_opt_get(legacy_opts, "boot") != NULL) { ++ fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be " ++ "ignored. Future versions will reject this parameter. Please " ++ "update your scripts.\n"); ++ } ++ + /* Media type */ + value = qemu_opt_get(legacy_opts, "media"); + if (value) { +@@ -1890,10 +1895,6 @@ QemuOptsList qemu_common_drive_opts = { + .name = "copy-on-read", + .type = QEMU_OPT_BOOL, + .help = "copy read data from backing file into image file", +- },{ +- .name = "boot", +- .type = QEMU_OPT_BOOL, +- .help = "(deprecated, ignored)", + }, + { /* end of list */ } + }, +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Move-parsing-of-if-option-to-drive_init.patch b/SOURCES/kvm-blockdev-Move-parsing-of-if-option-to-drive_init.patch new file mode 100644 index 0000000..6dd8885 --- /dev/null +++ b/SOURCES/kvm-blockdev-Move-parsing-of-if-option-to-drive_init.patch @@ -0,0 +1,127 @@ +From d3346d7e6dea698bc00eb18be4e174e9036ebeee Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:05 +0100 +Subject: [PATCH 52/87] blockdev: Move parsing of 'if' option to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-12-git-send-email-kwolf@redhat.com> +Patchwork-id: 55390 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 11/24] blockdev: Move parsing of 'if' option to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +It's always IF_NONE for blockdev-add. + +Signed-off-by: Kevin Wolf +Reviewed-by: Benoit Canet +Reviewed-by: Eric Blake +(cherry picked from commit 593d464bd43900c2a0c8800b76212f6a93e99a0d) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 40 ++++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 18 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 40 ++++++++++++++++++++++------------------ + 1 files changed, 22 insertions(+), 18 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index e6d3c15..9bc3417 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -328,14 +328,13 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; + + /* Takes the ownership of bs_opts */ + static DriveInfo *blockdev_init(QDict *bs_opts, +- BlockInterfaceType block_default_type, ++ BlockInterfaceType type, + DriveMediaType media) + { + const char *buf; + const char *file = NULL; + const char *serial; + const char *mediastr = ""; +- BlockInterfaceType type; + int bus_id, unit_id; + int cyls, heads, secs, translation; + int max_devs; +@@ -396,17 +395,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + file = qemu_opt_get(opts, "file"); + serial = qemu_opt_get(opts, "serial"); + +- if ((buf = qemu_opt_get(opts, "if")) != NULL) { +- for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++) +- ; +- if (type == IF_COUNT) { +- error_report("unsupported bus type '%s'", buf); +- return NULL; +- } +- } else { +- type = block_default_type; +- } +- + max_devs = if_max_devs[type]; + + if (cyls || heads || secs) { +@@ -753,6 +741,10 @@ QemuOptsList qemu_legacy_drive_opts = { + .name = "media", + .type = QEMU_OPT_STRING, + .help = "media type (disk, cdrom)", ++ },{ ++ .name = "if", ++ .type = QEMU_OPT_STRING, ++ .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", + }, + { /* end of list */ } + }, +@@ -765,6 +757,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + QDict *bs_opts; + QemuOpts *legacy_opts; + DriveMediaType media = MEDIA_DISK; ++ BlockInterfaceType type; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -828,8 +821,23 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + } + ++ /* Controller type */ ++ value = qemu_opt_get(legacy_opts, "if"); ++ if (value) { ++ for (type = 0; ++ type < IF_COUNT && strcmp(value, if_name[type]); ++ type++) { ++ } ++ if (type == IF_COUNT) { ++ error_report("unsupported bus type '%s'", value); ++ goto fail; ++ } ++ } else { ++ type = block_default_type; ++ } ++ + /* Actual block device init: Functionality shared with blockdev-add */ +- dinfo = blockdev_init(bs_opts, block_default_type, media); ++ dinfo = blockdev_init(bs_opts, type, media); + if (dinfo == NULL) { + goto fail; + } +@@ -1781,10 +1789,6 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_NUMBER, + .help = "unit number (i.e. lun for scsi)", + },{ +- .name = "if", +- .type = QEMU_OPT_STRING, +- .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", +- },{ + .name = "index", + .type = QEMU_OPT_NUMBER, + .help = "index number", +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Move-parsing-of-media-option-to-drive_init.patch b/SOURCES/kvm-blockdev-Move-parsing-of-media-option-to-drive_init.patch new file mode 100644 index 0000000..0f753bc --- /dev/null +++ b/SOURCES/kvm-blockdev-Move-parsing-of-media-option-to-drive_init.patch @@ -0,0 +1,182 @@ +From 90321b7139eb0c078f2dffa2d78a121852389e40 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:04 +0100 +Subject: [PATCH 51/87] blockdev: Move parsing of 'media' option to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-11-git-send-email-kwolf@redhat.com> +Patchwork-id: 55389 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 10/24] blockdev: Move parsing of 'media' option to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +This moves as much as possible of the processing of the 'media' option +to drive_init so that it can only be accessed using legacy functions, +but never with anything blockdev-add related. + +Signed-off-by: Kevin Wolf +Reviewed-by: Benoit Canet +Reviewed-by: Eric Blake +(cherry picked from commit 33cb7dc8b7a26ccdff2f054056d3f2e487cbb4cd) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 73 ++++++++++++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 50 insertions(+), 23 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 73 +++++++++++++++++++++++++++++++++++++++++------------------- + 1 files changed, 50 insertions(+), 23 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 8dd9fd7..e6d3c15 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -324,16 +324,18 @@ static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp) + return true; + } + ++typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; ++ + /* Takes the ownership of bs_opts */ + static DriveInfo *blockdev_init(QDict *bs_opts, +- BlockInterfaceType block_default_type) ++ BlockInterfaceType block_default_type, ++ DriveMediaType media) + { + const char *buf; + const char *file = NULL; + const char *serial; + const char *mediastr = ""; + BlockInterfaceType type; +- enum { MEDIA_DISK, MEDIA_CDROM } media; + int bus_id, unit_id; + int cyls, heads, secs, translation; + int max_devs; +@@ -354,7 +356,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + BlockDriver *drv = NULL; + + translation = BIOS_ATA_TRANSLATION_AUTO; +- media = MEDIA_DISK; + + /* Check common options by copying from bs_opts to opts, all other options + * stay in bs_opts for processing by bdrv_open(). */ +@@ -441,19 +442,11 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + } + } + +- if ((buf = qemu_opt_get(opts, "media")) != NULL) { +- if (!strcmp(buf, "disk")) { +- media = MEDIA_DISK; +- } else if (!strcmp(buf, "cdrom")) { +- if (cyls || secs || heads) { +- error_report("CHS can't be set with media=%s", buf); +- return NULL; +- } +- media = MEDIA_CDROM; +- } else { +- error_report("'%s' invalid media", buf); +- return NULL; +- } ++ if (media == MEDIA_CDROM) { ++ if (cyls || secs || heads) { ++ error_report("CHS can't be set with media=cdrom"); ++ return NULL; ++ } + } + + if ((buf = qemu_opt_get(opts, "discard")) != NULL) { +@@ -752,11 +745,27 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to) + } + } + ++QemuOptsList qemu_legacy_drive_opts = { ++ .name = "drive", ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_legacy_drive_opts.head), ++ .desc = { ++ { ++ .name = "media", ++ .type = QEMU_OPT_STRING, ++ .help = "media type (disk, cdrom)", ++ }, ++ { /* end of list */ } ++ }, ++}; ++ + DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + { + const char *value; +- DriveInfo *dinfo; ++ DriveInfo *dinfo = NULL; + QDict *bs_opts; ++ QemuOpts *legacy_opts; ++ DriveMediaType media = MEDIA_DISK; ++ Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ + qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); +@@ -798,8 +807,29 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + bs_opts = qdict_new(); + qemu_opts_to_qdict(all_opts, bs_opts); + ++ legacy_opts = qemu_opts_create_nofail(&qemu_legacy_drive_opts); ++ qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err); ++ if (error_is_set(&local_err)) { ++ qerror_report_err(local_err); ++ error_free(local_err); ++ goto fail; ++ } ++ ++ /* Media type */ ++ value = qemu_opt_get(legacy_opts, "media"); ++ if (value) { ++ if (!strcmp(value, "disk")) { ++ media = MEDIA_DISK; ++ } else if (!strcmp(value, "cdrom")) { ++ media = MEDIA_CDROM; ++ } else { ++ error_report("'%s' invalid media", value); ++ goto fail; ++ } ++ } ++ + /* Actual block device init: Functionality shared with blockdev-add */ +- dinfo = blockdev_init(bs_opts, block_default_type); ++ dinfo = blockdev_init(bs_opts, block_default_type, media); + if (dinfo == NULL) { + goto fail; + } +@@ -809,6 +839,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + dinfo->opts = all_opts; + + fail: ++ qemu_opts_del(legacy_opts); + return dinfo; + } + +@@ -1705,7 +1736,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + + qdict_flatten(qdict); + +- dinfo = blockdev_init(qdict, IF_NONE); ++ dinfo = blockdev_init(qdict, IF_NONE, MEDIA_DISK); + if (!dinfo) { + error_setg(errp, "Could not open image"); + goto fail; +@@ -1774,10 +1805,6 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_STRING, + .help = "chs translation (auto, lba. none)", + },{ +- .name = "media", +- .type = QEMU_OPT_STRING, +- .help = "media type (disk, cdrom)", +- },{ + .name = "snapshot", + .type = QEMU_OPT_BOOL, + .help = "enable/disable snapshot mode", +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Move-virtio-blk-device-creation-to-drive_in.patch b/SOURCES/kvm-blockdev-Move-virtio-blk-device-creation-to-drive_in.patch new file mode 100644 index 0000000..244e7fa --- /dev/null +++ b/SOURCES/kvm-blockdev-Move-virtio-blk-device-creation-to-drive_in.patch @@ -0,0 +1,154 @@ +From 1a3ba7716b6559be0e4a236c96229b98eb92d9a6 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:09 +0100 +Subject: [PATCH 56/87] blockdev: Move virtio-blk device creation to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-16-git-send-email-kwolf@redhat.com> +Patchwork-id: 55394 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 15/24] blockdev: Move virtio-blk device creation to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit 394c7d4d6bd06386308e2fef0cf1c613a10e0d23) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 54 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 27 insertions(+), 27 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 54 +++++++++++++++++++++++++++--------------------------- + 1 files changed, 27 insertions(+), 27 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index b6dff50..14b357a 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -337,7 +337,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + int ro = 0; + int bdrv_flags = 0; + int on_read_error, on_write_error; +- const char *devaddr; + DriveInfo *dinfo; + BlockIOLimit io_limits; + int snapshot = 0; +@@ -472,20 +471,12 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + } + } + +- if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) { +- if (type != IF_VIRTIO) { +- error_report("addr is not supported by this bus type"); +- return NULL; +- } +- } +- + /* init */ + dinfo = g_malloc0(sizeof(*dinfo)); + dinfo->id = g_strdup(qemu_opts_id(opts)); + dinfo->bdrv = bdrv_new(dinfo->id); + dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; + dinfo->bdrv->read_only = ro; +- dinfo->devaddr = devaddr; + dinfo->type = type; + dinfo->refcount = 1; + if (serial != NULL) { +@@ -509,22 +500,8 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + case IF_FLOPPY: + case IF_PFLASH: + case IF_MTD: +- break; + case IF_VIRTIO: +- { +- /* add virtio block device */ +- QemuOpts *devopts; +- devopts = qemu_opts_create_nofail(qemu_find_opts("device")); +- if (arch_type == QEMU_ARCH_S390X) { +- qemu_opt_set(devopts, "driver", "virtio-blk-s390"); +- } else { +- qemu_opt_set(devopts, "driver", "virtio-blk-pci"); +- } +- qemu_opt_set(devopts, "drive", dinfo->id); +- if (devaddr) +- qemu_opt_set(devopts, "addr", devaddr); + break; +- } + default: + abort(); + } +@@ -648,6 +625,10 @@ QemuOptsList qemu_legacy_drive_opts = { + .name = "boot", + .type = QEMU_OPT_BOOL, + .help = "(deprecated, ignored)", ++ },{ ++ .name = "addr", ++ .type = QEMU_OPT_STRING, ++ .help = "pci address (virtio only)", + }, + { /* end of list */ } + }, +@@ -663,6 +644,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + BlockInterfaceType type; + int cyls, heads, secs, translation; + int max_devs, bus_id, unit_id, index; ++ const char *devaddr; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -852,6 +834,27 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + g_free(new_id); + } + ++ /* Add virtio block device */ ++ devaddr = qemu_opt_get(legacy_opts, "addr"); ++ if (devaddr && type != IF_VIRTIO) { ++ error_report("addr is not supported by this bus type"); ++ goto fail; ++ } ++ ++ if (type == IF_VIRTIO) { ++ QemuOpts *devopts; ++ devopts = qemu_opts_create_nofail(qemu_find_opts("device")); ++ if (arch_type == QEMU_ARCH_S390X) { ++ qemu_opt_set(devopts, "driver", "virtio-blk-s390"); ++ } else { ++ qemu_opt_set(devopts, "driver", "virtio-blk-pci"); ++ } ++ qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id")); ++ if (devaddr) { ++ qemu_opt_set(devopts, "addr", devaddr); ++ } ++ } ++ + /* Actual block device init: Functionality shared with blockdev-add */ + dinfo = blockdev_init(bs_opts, type, media); + if (dinfo == NULL) { +@@ -869,6 +872,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + + dinfo->bus = bus_id; + dinfo->unit = unit_id; ++ dinfo->devaddr = devaddr; + + fail: + qemu_opts_del(legacy_opts); +@@ -1849,10 +1853,6 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_STRING, + .help = "write error action", + },{ +- .name = "addr", +- .type = QEMU_OPT_STRING, +- .help = "pci address (virtio only)", +- },{ + .name = "read-only", + .type = QEMU_OPT_BOOL, + .help = "open drive file as read-only", +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Moving-parsing-of-geometry-options-to-drive.patch b/SOURCES/kvm-blockdev-Moving-parsing-of-geometry-options-to-drive.patch new file mode 100644 index 0000000..c8a10ab --- /dev/null +++ b/SOURCES/kvm-blockdev-Moving-parsing-of-geometry-options-to-drive.patch @@ -0,0 +1,245 @@ +From b434963222bd7ce4b4a7ff493217f3ab00ac734c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:06 +0100 +Subject: [PATCH 53/87] blockdev: Moving parsing of geometry options to drive_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-13-git-send-email-kwolf@redhat.com> +Patchwork-id: 55391 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 12/24] blockdev: Moving parsing of geometry options to drive_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +This moves all of the geometry options (cyls/heads/secs/trans) to +drive_init so that they can only be accessed using legacy functions, but +never with anything blockdev-add related. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit b41a7338cfdeeb913ee4846d79a3f7e221350aed) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 136 +++++++++++++++++++++++++++++++------------------------------ + 1 file changed, 69 insertions(+), 67 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 136 ++++++++++++++++++++++++++++++----------------------------- + 1 files changed, 69 insertions(+), 67 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 9bc3417..d69c4a8 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -336,7 +336,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + const char *serial; + const char *mediastr = ""; + int bus_id, unit_id; +- int cyls, heads, secs, translation; + int max_devs; + int index; + int ro = 0; +@@ -354,8 +353,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + bool has_driver_specific_opts; + BlockDriver *drv = NULL; + +- translation = BIOS_ATA_TRANSLATION_AUTO; +- + /* Check common options by copying from bs_opts to opts, all other options + * stay in bs_opts for processing by bdrv_open(). */ + id = qdict_get_try_str(bs_opts, "id"); +@@ -384,10 +381,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + unit_id = qemu_opt_get_number(opts, "unit", -1); + index = qemu_opt_get_number(opts, "index", -1); + +- cyls = qemu_opt_get_number(opts, "cyls", 0); +- heads = qemu_opt_get_number(opts, "heads", 0); +- secs = qemu_opt_get_number(opts, "secs", 0); +- + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); + ro = qemu_opt_get_bool(opts, "read-only", 0); + copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false); +@@ -397,46 +390,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + + max_devs = if_max_devs[type]; + +- if (cyls || heads || secs) { +- if (cyls < 1) { +- error_report("invalid physical cyls number"); +- return NULL; +- } +- if (heads < 1) { +- error_report("invalid physical heads number"); +- return NULL; +- } +- if (secs < 1) { +- error_report("invalid physical secs number"); +- return NULL; +- } +- } +- +- if ((buf = qemu_opt_get(opts, "trans")) != NULL) { +- if (!cyls) { +- error_report("'%s' trans must be used with cyls, heads and secs", +- buf); +- return NULL; +- } +- if (!strcmp(buf, "none")) +- translation = BIOS_ATA_TRANSLATION_NONE; +- else if (!strcmp(buf, "lba")) +- translation = BIOS_ATA_TRANSLATION_LBA; +- else if (!strcmp(buf, "auto")) +- translation = BIOS_ATA_TRANSLATION_AUTO; +- else { +- error_report("'%s' invalid translation type", buf); +- return NULL; +- } +- } +- +- if (media == MEDIA_CDROM) { +- if (cyls || secs || heads) { +- error_report("CHS can't be set with media=cdrom"); +- return NULL; +- } +- } +- + if ((buf = qemu_opt_get(opts, "discard")) != NULL) { + if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) { + error_report("invalid discard option"); +@@ -612,10 +565,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + dinfo->type = type; + dinfo->bus = bus_id; + dinfo->unit = unit_id; +- dinfo->cyls = cyls; +- dinfo->heads = heads; +- dinfo->secs = secs; +- dinfo->trans = translation; + dinfo->refcount = 1; + if (serial != NULL) { + dinfo->serial = g_strdup(serial); +@@ -745,6 +694,22 @@ QemuOptsList qemu_legacy_drive_opts = { + .name = "if", + .type = QEMU_OPT_STRING, + .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)", ++ },{ ++ .name = "cyls", ++ .type = QEMU_OPT_NUMBER, ++ .help = "number of cylinders (ide disk geometry)", ++ },{ ++ .name = "heads", ++ .type = QEMU_OPT_NUMBER, ++ .help = "number of heads (ide disk geometry)", ++ },{ ++ .name = "secs", ++ .type = QEMU_OPT_NUMBER, ++ .help = "number of sectors (ide disk geometry)", ++ },{ ++ .name = "trans", ++ .type = QEMU_OPT_STRING, ++ .help = "chs translation (auto, lba, none)", + }, + { /* end of list */ } + }, +@@ -758,6 +723,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + QemuOpts *legacy_opts; + DriveMediaType media = MEDIA_DISK; + BlockInterfaceType type; ++ int cyls, heads, secs, translation; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -836,6 +802,53 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + type = block_default_type; + } + ++ /* Geometry */ ++ cyls = qemu_opt_get_number(legacy_opts, "cyls", 0); ++ heads = qemu_opt_get_number(legacy_opts, "heads", 0); ++ secs = qemu_opt_get_number(legacy_opts, "secs", 0); ++ ++ if (cyls || heads || secs) { ++ if (cyls < 1) { ++ error_report("invalid physical cyls number"); ++ goto fail; ++ } ++ if (heads < 1) { ++ error_report("invalid physical heads number"); ++ goto fail; ++ } ++ if (secs < 1) { ++ error_report("invalid physical secs number"); ++ goto fail; ++ } ++ } ++ ++ translation = BIOS_ATA_TRANSLATION_AUTO; ++ value = qemu_opt_get(legacy_opts, "trans"); ++ if (value != NULL) { ++ if (!cyls) { ++ error_report("'%s' trans must be used with cyls, heads and secs", ++ value); ++ goto fail; ++ } ++ if (!strcmp(value, "none")) { ++ translation = BIOS_ATA_TRANSLATION_NONE; ++ } else if (!strcmp(value, "lba")) { ++ translation = BIOS_ATA_TRANSLATION_LBA; ++ } else if (!strcmp(value, "auto")) { ++ translation = BIOS_ATA_TRANSLATION_AUTO; ++ } else { ++ error_report("'%s' invalid translation type", value); ++ goto fail; ++ } ++ } ++ ++ if (media == MEDIA_CDROM) { ++ if (cyls || secs || heads) { ++ error_report("CHS can't be set with media=cdrom"); ++ goto fail; ++ } ++ } ++ + /* Actual block device init: Functionality shared with blockdev-add */ + dinfo = blockdev_init(bs_opts, type, media); + if (dinfo == NULL) { +@@ -846,6 +859,11 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + dinfo->enable_auto_del = true; + dinfo->opts = all_opts; + ++ dinfo->cyls = cyls; ++ dinfo->heads = heads; ++ dinfo->secs = secs; ++ dinfo->trans = translation; ++ + fail: + qemu_opts_del(legacy_opts); + return dinfo; +@@ -1793,22 +1811,6 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_NUMBER, + .help = "index number", + },{ +- .name = "cyls", +- .type = QEMU_OPT_NUMBER, +- .help = "number of cylinders (ide disk geometry)", +- },{ +- .name = "heads", +- .type = QEMU_OPT_NUMBER, +- .help = "number of heads (ide disk geometry)", +- },{ +- .name = "secs", +- .type = QEMU_OPT_NUMBER, +- .help = "number of sectors (ide disk geometry)", +- },{ +- .name = "trans", +- .type = QEMU_OPT_STRING, +- .help = "chs translation (auto, lba. none)", +- },{ + .name = "snapshot", + .type = QEMU_OPT_BOOL, + .help = "enable/disable snapshot mode", +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Pass-QDict-to-blockdev_init.patch b/SOURCES/kvm-blockdev-Pass-QDict-to-blockdev_init.patch new file mode 100644 index 0000000..823b5ad --- /dev/null +++ b/SOURCES/kvm-blockdev-Pass-QDict-to-blockdev_init.patch @@ -0,0 +1,151 @@ +From 615669f863855880e3adfcc8046e34cdc6d7e8d6 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:03 +0100 +Subject: [PATCH 50/87] blockdev: Pass QDict to blockdev_init() + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-10-git-send-email-kwolf@redhat.com> +Patchwork-id: 55388 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 09/24] blockdev: Pass QDict to blockdev_init() +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +Working on a QDict instead of a QemuOpts that accepts anything is more +in line with bdrv_open(). A QDict is what qmp_blockdev_add() already has +anyway, so this saves additional conversions. And last, but not least, +it allows later patches to easily extract legacy options into a +separate, typed QemuOpts for drive_init() (the untyped QemuOpts that +drive_init already has doesn't allow access to numbers, only strings, +and is therefore useless without conversion). + +Signed-off-by: Kevin Wolf +Reviewed-by: Benoit Canet +Reviewed-by: Eric Blake +(cherry picked from commit f298d071662af6cf5dc221ee3e3bd0154035e570) + +Conflicts: + blockdev.c + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 34 +++++++++++++++++----------------- + 1 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 03ee554..8dd9fd7 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -217,7 +217,10 @@ static void bdrv_format_print(void *opaque, const char *name) + + static void drive_uninit(DriveInfo *dinfo) + { +- qemu_opts_del(dinfo->opts); ++ if (dinfo->opts) { ++ qemu_opts_del(dinfo->opts); ++ } ++ + bdrv_delete(dinfo->bdrv); + g_free(dinfo->id); + QTAILQ_REMOVE(&drives, dinfo, next); +@@ -321,7 +324,8 @@ static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp) + return true; + } + +-static DriveInfo *blockdev_init(QemuOpts *all_opts, ++/* Takes the ownership of bs_opts */ ++static DriveInfo *blockdev_init(QDict *bs_opts, + BlockInterfaceType block_default_type) + { + const char *buf; +@@ -345,7 +349,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + int ret; + Error *error = NULL; + QemuOpts *opts; +- QDict *bs_opts; + const char *id; + bool has_driver_specific_opts; + BlockDriver *drv = NULL; +@@ -353,9 +356,9 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + translation = BIOS_ATA_TRANSLATION_AUTO; + media = MEDIA_DISK; + +- /* Check common options by copying from all_opts to opts, all other options +- * are stored in bs_opts. */ +- id = qemu_opts_id(all_opts); ++ /* Check common options by copying from bs_opts to opts, all other options ++ * stay in bs_opts for processing by bdrv_open(). */ ++ id = qdict_get_try_str(bs_opts, "id"); + opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error); + if (error_is_set(&error)) { + qerror_report_err(error); +@@ -363,8 +366,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + return NULL; + } + +- bs_opts = qdict_new(); +- qemu_opts_to_qdict(all_opts, bs_opts); + qemu_opts_absorb_qdict(opts, bs_opts, &error); + if (error_is_set(&error)) { + qerror_report_err(error); +@@ -634,7 +635,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + dinfo->heads = heads; + dinfo->secs = secs; + dinfo->trans = translation; +- dinfo->opts = all_opts; + dinfo->refcount = 1; + if (serial != NULL) { + dinfo->serial = g_strdup(serial); +@@ -756,6 +756,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + { + const char *value; + DriveInfo *dinfo; ++ QDict *bs_opts; + + /* Change legacy command line options into QMP ones */ + qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); +@@ -793,14 +794,19 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + qemu_opt_unset(all_opts, "cache"); + } + ++ /* Get a QDict for processing the options */ ++ bs_opts = qdict_new(); ++ qemu_opts_to_qdict(all_opts, bs_opts); ++ + /* Actual block device init: Functionality shared with blockdev-add */ +- dinfo = blockdev_init(all_opts, block_default_type); ++ dinfo = blockdev_init(bs_opts, block_default_type); + if (dinfo == NULL) { + goto fail; + } + + /* Set legacy DriveInfo fields */ + dinfo->enable_auto_del = true; ++ dinfo->opts = all_opts; + + fail: + return dinfo; +@@ -1699,13 +1705,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + + qdict_flatten(qdict); + +- QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err); +- if (error_is_set(&local_err)) { +- error_propagate(errp, local_err); +- goto fail; +- } +- +- dinfo = blockdev_init(opts, IF_NONE); ++ dinfo = blockdev_init(qdict, IF_NONE); + if (!dinfo) { + error_setg(errp, "Could not open image"); + goto fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Remove-IF_-check-for-read-only-blockdev_ini.patch b/SOURCES/kvm-blockdev-Remove-IF_-check-for-read-only-blockdev_ini.patch new file mode 100644 index 0000000..e41e0f6 --- /dev/null +++ b/SOURCES/kvm-blockdev-Remove-IF_-check-for-read-only-blockdev_ini.patch @@ -0,0 +1,231 @@ +From 6048f02ce5388f14c0ff1a77122d26be9dffcac0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 7 Nov 2013 12:41:46 +0100 +Subject: [PATCH 57/87] blockdev: Remove IF_* check for read-only blockdev_init + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-17-git-send-email-kwolf@redhat.com> +Patchwork-id: 55395 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 16/24] blockdev: Remove IF_* check for read-only blockdev_init +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +IF_NONE allows read-only, which makes forbidding it in this place +for other types pretty much pointless. + +Instead, make sure that all devices for which the check would have +errored out check in their init function that they don't get a read-only +BlockDriverState. This catches even cases where IF_NONE and -device is +used. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 4f8a066b5fc254eeaabbbde56ba4f5b29cc68fdf) + +Conflicts: + hw/block/xen_disk.c + hw/sd/milkymist-memcard.c + hw/sd/omap_mmc.c + hw/sd/pl181.c + hw/sd/pxa2xx_mmci.c + hw/sd/sdhci.c + hw/sd/ssi-sd.c + +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 6 ------ + hw/block/m25p80.c | 5 +++++ + hw/block/xen_disk.c | 5 +++++ + hw/sd/milkymist-memcard.c | 4 ++++ + hw/sd/omap_mmc.c | 6 ++++++ + hw/sd/pl181.c | 4 ++++ + hw/sd/pxa2xx_mmci.c | 3 +++ + hw/sd/sd.c | 5 +++++ + hw/sd/sdhci.c | 3 +++ + hw/sd/ssi-sd.c | 3 +++ + tests/qemu-iotests/051.out | 5 ++++- + 11 files changed, 42 insertions(+), 7 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 14b357a..680ba22 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -529,12 +529,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + if (media == MEDIA_CDROM) { + /* CDROM is fine for any interface, don't check. */ + ro = 1; +- } else if (ro == 1) { +- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && +- type != IF_NONE && type != IF_PFLASH) { +- error_report("read-only not supported by this bus type"); +- goto err; +- } + } + + bdrv_flags |= ro ? 0 : BDRV_O_RDWR; +diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c +index 759c84d..ccec5ab 100644 +--- a/hw/block/m25p80.c ++++ b/hw/block/m25p80.c +@@ -619,6 +619,11 @@ static int m25p80_init(SSISlave *ss) + if (dinfo && dinfo->bdrv) { + DB_PRINT_L(0, "Binding to IF_MTD drive\n"); + s->bdrv = dinfo->bdrv; ++ if (bdrv_is_read_only(s->bdrv)) { ++ fprintf(stderr, "Can't use a read-only drive"); ++ return 1; ++ } ++ + /* FIXME: Move to late init */ + if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size, + BDRV_SECTOR_SIZE))) { +diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c +index 2d4d263..498f2e9 100644 +--- a/hw/block/xen_disk.c ++++ b/hw/block/xen_disk.c +@@ -817,6 +817,11 @@ static int blk_connect(struct XenDevice *xendev) + /* setup via qemu cmdline -> already setup for us */ + xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n"); + blkdev->bs = blkdev->dinfo->bdrv; ++ if (bdrv_is_read_only(blkdev->bs) && !readonly) { ++ xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive"); ++ blkdev->bs = NULL; ++ return -1; ++ } + } + bdrv_attach_dev_nofail(blkdev->bs, blkdev); + blkdev->file_size = bdrv_getlength(blkdev->bs); +diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c +index d5944bc..a7dfbff 100644 +--- a/hw/sd/milkymist-memcard.c ++++ b/hw/sd/milkymist-memcard.c +@@ -251,6 +251,10 @@ static int milkymist_memcard_init(SysBusDevice *dev) + + dinfo = drive_get_next(IF_SD); + s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0); ++ if (s->card == NULL) { ++ return -1; ++ } ++ + s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0; + + memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s, +diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c +index d4079cd..aefdc3e 100644 +--- a/hw/sd/omap_mmc.c ++++ b/hw/sd/omap_mmc.c +@@ -593,6 +593,9 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base, + + /* Instantiate the storage */ + s->card = sd_init(bd, 0); ++ if (s->card == NULL) { ++ exit(1); ++ } + + return s; + } +@@ -618,6 +621,9 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, + + /* Instantiate the storage */ + s->card = sd_init(bd, 0); ++ if (s->card == NULL) { ++ exit(1); ++ } + + s->cdet = qemu_allocate_irqs(omap_mmc_cover_cb, s, 1)[0]; + sd_set_cb(s->card, NULL, s->cdet); +diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c +index c5ad890..a7f85b8 100644 +--- a/hw/sd/pl181.c ++++ b/hw/sd/pl181.c +@@ -486,6 +486,10 @@ static int pl181_init(SysBusDevice *dev) + qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2); + dinfo = drive_get_next(IF_SD); + s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0); ++ if (s->card == NULL) { ++ return -1; ++ } ++ + return 0; + } + +diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c +index 2db1cab..066d523 100644 +--- a/hw/sd/pxa2xx_mmci.c ++++ b/hw/sd/pxa2xx_mmci.c +@@ -539,6 +539,9 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, + + /* Instantiate the actual storage */ + s->card = sd_init(bd, 0); ++ if (s->card == NULL) { ++ exit(1); ++ } + + register_savevm(NULL, "pxa2xx_mmci", 0, 0, + pxa2xx_mmci_save, pxa2xx_mmci_load, s); +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index 2e0ef3e..e816c78 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -492,6 +492,11 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi) + { + SDState *sd; + ++ if (bdrv_is_read_only(bs)) { ++ fprintf(stderr, "sd_init: Cannot use read-only drive\n"); ++ return NULL; ++ } ++ + sd = (SDState *) g_malloc0(sizeof(SDState)); + sd->buf = qemu_blockalign(bs, 512); + sd->spi = is_spi; +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 91dc9b0..d8a4987 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1166,6 +1166,9 @@ static void sdhci_initfn(Object *obj) + + di = drive_get_next(IF_SD); + s->card = sd_init(di ? di->bdrv : NULL, 0); ++ if (s->card == NULL) { ++ exit(1); ++ } + s->eject_cb = qemu_allocate_irqs(sdhci_insert_eject_cb, s, 1)[0]; + s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0]; + sd_set_cb(s->card, s->ro_cb, s->eject_cb); +diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c +index 4d3c4f6..79ec51a 100644 +--- a/hw/sd/ssi-sd.c ++++ b/hw/sd/ssi-sd.c +@@ -246,6 +246,9 @@ static int ssi_sd_init(SSISlave *dev) + s->mode = SSI_SD_CMD; + dinfo = drive_get_next(IF_SD); + s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, 1); ++ if (s->sd == NULL) { ++ return -1; ++ } + register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s); + return 0; + } +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 54a6b3a..4fca1ca 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -98,7 +98,10 @@ QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) QEMU_PROG: Can't use a read-only drive ++QEMU_PROG: Device initialization failed. ++QEMU_PROG: Initialization of device ide-hd failed + + Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on + QEMU X.Y.Z monitor - type 'help' for more information +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Remove-media-parameter-from-blockdev_init.patch b/SOURCES/kvm-blockdev-Remove-media-parameter-from-blockdev_init.patch new file mode 100644 index 0000000..ccf803d --- /dev/null +++ b/SOURCES/kvm-blockdev-Remove-media-parameter-from-blockdev_init.patch @@ -0,0 +1,132 @@ +From 0c82774abd19c0f11b5cca29be188176d6f447ef Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:12 +0100 +Subject: [PATCH 59/87] blockdev: Remove 'media' parameter from blockdev_init() + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-19-git-send-email-kwolf@redhat.com> +Patchwork-id: 55396 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 18/24] blockdev: Remove 'media' parameter from blockdev_init() +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +The remaining users shouldn't be there with blockdev-add and are easy to +move to drive_init(). + +Bonus bug fix: As a side effect, CD-ROM drives can now use block drivers +on the read-only whitelist without explicitly specifying read-only=on, +even if a format is explicitly specified. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit e34ef046412431acf5b4e30762390b4048187bb8) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 40 +++++++++++++++------------------------- + 1 file changed, 15 insertions(+), 25 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 40 +++++++++++++++------------------------- + 1 files changed, 15 insertions(+), 25 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 680ba22..d4b18c5 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -328,8 +328,7 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; + + /* Takes the ownership of bs_opts */ + static DriveInfo *blockdev_init(QDict *bs_opts, +- BlockInterfaceType type, +- DriveMediaType media) ++ BlockInterfaceType type) + { + const char *buf; + const char *file = NULL; +@@ -489,22 +488,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + /* disk I/O throttling */ + bdrv_set_io_limits(dinfo->bdrv, &io_limits); + +- switch(type) { +- case IF_IDE: +- case IF_SCSI: +- case IF_XEN: +- case IF_NONE: +- dinfo->media_cd = media == MEDIA_CDROM; +- break; +- case IF_SD: +- case IF_FLOPPY: +- case IF_PFLASH: +- case IF_MTD: +- case IF_VIRTIO: +- break; +- default: +- abort(); +- } + if (!file || !*file) { + if (has_driver_specific_opts) { + file = NULL; +@@ -526,11 +509,6 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + bdrv_flags |= BDRV_O_INCOMING; + } + +- if (media == MEDIA_CDROM) { +- /* CDROM is fine for any interface, don't check. */ +- ro = 1; +- } +- + bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + + if (ro && copy_on_read) { +@@ -703,6 +681,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + media = MEDIA_DISK; + } else if (!strcmp(value, "cdrom")) { + media = MEDIA_CDROM; ++ qdict_put(bs_opts, "read-only", qstring_from_str("on")); + } else { + error_report("'%s' invalid media", value); + goto fail; +@@ -850,7 +829,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + + /* Actual block device init: Functionality shared with blockdev-add */ +- dinfo = blockdev_init(bs_opts, type, media); ++ dinfo = blockdev_init(bs_opts, type); + if (dinfo == NULL) { + goto fail; + } +@@ -868,6 +847,17 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + dinfo->unit = unit_id; + dinfo->devaddr = devaddr; + ++ switch(type) { ++ case IF_IDE: ++ case IF_SCSI: ++ case IF_XEN: ++ case IF_NONE: ++ dinfo->media_cd = media == MEDIA_CDROM; ++ break; ++ default: ++ break; ++ } ++ + fail: + qemu_opts_del(legacy_opts); + return dinfo; +@@ -1766,7 +1756,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + + qdict_flatten(qdict); + +- dinfo = blockdev_init(qdict, IF_NONE, MEDIA_DISK); ++ dinfo = blockdev_init(qdict, IF_NONE); + if (!dinfo) { + error_setg(errp, "Could not open image"); + goto fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Rename-I-O-throttling-options-for-QMP.patch b/SOURCES/kvm-blockdev-Rename-I-O-throttling-options-for-QMP.patch new file mode 100644 index 0000000..d027299 --- /dev/null +++ b/SOURCES/kvm-blockdev-Rename-I-O-throttling-options-for-QMP.patch @@ -0,0 +1,145 @@ +From 6407962af839506d7dcd956d48986324264a3587 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:19 +0200 +Subject: [PATCH 28/38] blockdev: Rename I/O throttling options for QMP + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-29-git-send-email-kwolf@redhat.com> +Patchwork-id: 54215 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 28/32] blockdev: Rename I/O throttling options for QMP +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +In QMP, we want to use dashes instead of underscores in QMP argument +names, and use nested options for throttling. + +The new option names affect the command line as well, but for +compatibility drive_init() will convert the old option names before +calling into the code that will be shared between -drive and +blockdev-add. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 57975222b6a928dd4a4a8a7b37093cc8ecba5045) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 52 +++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 39 insertions(+), 13 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 52 +++++++++++++++++++++++++++++++++++++++------------- + 1 files changed, 39 insertions(+), 13 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 1c9ca4d..08b1aaf 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -312,7 +312,8 @@ static bool do_check_io_limits(BlockIOLimit *io_limits, Error **errp) + return true; + } + +-DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) ++static DriveInfo *blockdev_init(QemuOpts *all_opts, ++ BlockInterfaceType block_default_type) + { + const char *buf; + const char *file = NULL; +@@ -485,17 +486,17 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + + /* disk I/O throttling */ + io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = +- qemu_opt_get_number(opts, "bps", 0); ++ qemu_opt_get_number(opts, "throttling.bps-total", 0); + io_limits.bps[BLOCK_IO_LIMIT_READ] = +- qemu_opt_get_number(opts, "bps_rd", 0); ++ qemu_opt_get_number(opts, "throttling.bps-read", 0); + io_limits.bps[BLOCK_IO_LIMIT_WRITE] = +- qemu_opt_get_number(opts, "bps_wr", 0); ++ qemu_opt_get_number(opts, "throttling.bps-write", 0); + io_limits.iops[BLOCK_IO_LIMIT_TOTAL] = +- qemu_opt_get_number(opts, "iops", 0); ++ qemu_opt_get_number(opts, "throttling.iops-total", 0); + io_limits.iops[BLOCK_IO_LIMIT_READ] = +- qemu_opt_get_number(opts, "iops_rd", 0); ++ qemu_opt_get_number(opts, "throttling.iops-read", 0); + io_limits.iops[BLOCK_IO_LIMIT_WRITE] = +- qemu_opt_get_number(opts, "iops_wr", 0); ++ qemu_opt_get_number(opts, "throttling.iops-write", 0); + + if (!do_check_io_limits(&io_limits, &error)) { + error_report("%s", error_get_pretty(error)); +@@ -726,6 +727,31 @@ err: + return NULL; + } + ++static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to) ++{ ++ const char *value; ++ ++ value = qemu_opt_get(opts, from); ++ if (value) { ++ qemu_opt_set(opts, to, value); ++ qemu_opt_unset(opts, from); ++ } ++} ++ ++DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) ++{ ++ /* Change legacy command line options into QMP ones */ ++ qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); ++ qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read"); ++ qemu_opt_rename(all_opts, "iops_wr", "throttling.iops-write"); ++ ++ qemu_opt_rename(all_opts, "bps", "throttling.bps-total"); ++ qemu_opt_rename(all_opts, "bps_rd", "throttling.bps-read"); ++ qemu_opt_rename(all_opts, "bps_wr", "throttling.bps-write"); ++ ++ return blockdev_init(all_opts, block_default_type); ++} ++ + void do_commit(Monitor *mon, const QDict *qdict) + { + const char *device = qdict_get_str(qdict, "device"); +@@ -1679,27 +1705,27 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_BOOL, + .help = "open drive file as read-only", + },{ +- .name = "iops", ++ .name = "throttling.iops-total", + .type = QEMU_OPT_NUMBER, + .help = "limit total I/O operations per second", + },{ +- .name = "iops_rd", ++ .name = "throttling.iops-read", + .type = QEMU_OPT_NUMBER, + .help = "limit read operations per second", + },{ +- .name = "iops_wr", ++ .name = "throttling.iops-write", + .type = QEMU_OPT_NUMBER, + .help = "limit write operations per second", + },{ +- .name = "bps", ++ .name = "throttling.bps-total", + .type = QEMU_OPT_NUMBER, + .help = "limit total bytes per second", + },{ +- .name = "bps_rd", ++ .name = "throttling.bps-read", + .type = QEMU_OPT_NUMBER, + .help = "limit read bytes per second", + },{ +- .name = "bps_wr", ++ .name = "throttling.bps-write", + .type = QEMU_OPT_NUMBER, + .help = "limit write bytes per second", + },{ +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Rename-readonly-option-to-read-only.patch b/SOURCES/kvm-blockdev-Rename-readonly-option-to-read-only.patch new file mode 100644 index 0000000..9b70cdd --- /dev/null +++ b/SOURCES/kvm-blockdev-Rename-readonly-option-to-read-only.patch @@ -0,0 +1,92 @@ +From f093ad3c94cae221641ea0dd13ec3cf666a0fccd Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 19 Jul 2013 20:07:29 +0200 +Subject: [PATCH 30/38] blockdev: Rename 'readonly' option to 'read-only' + +Message-id: <1378736903-18489-31-git-send-email-kwolf@redhat.com> +Patchwork-id: 54217 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 30/32] blockdev: Rename 'readonly' option to 'read-only' +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Option name cleanup before it becomes a QMP API. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 0f227a947004aa9043d4386f4a47d6739499b88f) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 10 ++++++---- + tests/qemu-iotests/051.out | 2 +- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 08b1aaf..5d4f2f8 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -378,7 +378,7 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + secs = qemu_opt_get_number(opts, "secs", 0); + + snapshot = qemu_opt_get_bool(opts, "snapshot", 0); +- ro = qemu_opt_get_bool(opts, "readonly", 0); ++ ro = qemu_opt_get_bool(opts, "read-only", 0); + copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false); + + file = qemu_opt_get(opts, "file"); +@@ -684,7 +684,7 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + } else if (ro == 1) { + if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && + type != IF_NONE && type != IF_PFLASH) { +- error_report("readonly not supported by this bus type"); ++ error_report("read-only not supported by this bus type"); + goto err; + } + } +@@ -692,7 +692,7 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + bdrv_flags |= ro ? 0 : BDRV_O_RDWR; + + if (ro && copy_on_read) { +- error_report("warning: disabling copy_on_read on readonly drive"); ++ error_report("warning: disabling copy_on_read on read-only drive"); + } + + QINCREF(bs_opts); +@@ -749,6 +749,8 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + qemu_opt_rename(all_opts, "bps_rd", "throttling.bps-read"); + qemu_opt_rename(all_opts, "bps_wr", "throttling.bps-write"); + ++ qemu_opt_rename(all_opts, "readonly", "read-only"); ++ + return blockdev_init(all_opts, block_default_type); + } + +@@ -1701,7 +1703,7 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_STRING, + .help = "pci address (virtio only)", + },{ +- .name = "readonly", ++ .name = "read-only", + .type = QEMU_OPT_BOOL, + .help = "open drive file as read-only", + },{ +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 95ff245..8630382 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -137,7 +137,7 @@ QEMU 1.5.50 monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type + + Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on + QEMU 1.5.50 monitor - type 'help' for more information +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Separate-ID-generation-from-DriveInfo-creat.patch b/SOURCES/kvm-blockdev-Separate-ID-generation-from-DriveInfo-creat.patch new file mode 100644 index 0000000..dec43d4 --- /dev/null +++ b/SOURCES/kvm-blockdev-Separate-ID-generation-from-DriveInfo-creat.patch @@ -0,0 +1,114 @@ +From abc45043366f4031947a55c23ae0533d2409413e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:02 +0100 +Subject: [PATCH 49/87] blockdev: Separate ID generation from DriveInfo creation + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-9-git-send-email-kwolf@redhat.com> +Patchwork-id: 55387 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 08/24] blockdev: Separate ID generation from DriveInfo creation +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +blockdev-add shouldn't automatically generate IDs, but will keep most of +the DriveInfo creation code. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Wenchao Xia +Reviewed-by: Eric Blake +(cherry picked from commit 326642bc7f0ff95a0c08db527861a9a114a109da) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 32 +++++++++++++++++--------------- + include/qemu/option.h | 1 + + util/qemu-option.c | 6 ++++++ + 3 files changed, 24 insertions(+), 15 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 32 +++++++++++++++++--------------- + include/qemu/option.h | 1 + + util/qemu-option.c | 6 ++++++ + 3 files changed, 24 insertions(+), 15 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index d4f66db..03ee554 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -604,23 +604,25 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + return NULL; + } + +- /* init */ +- +- dinfo = g_malloc0(sizeof(*dinfo)); +- if ((buf = qemu_opts_id(opts)) != NULL) { +- dinfo->id = g_strdup(buf); +- } else { +- /* no id supplied -> create one */ +- dinfo->id = g_malloc0(32); +- if (type == IF_IDE || type == IF_SCSI) ++ /* no id supplied -> create one */ ++ if (qemu_opts_id(opts) == NULL) { ++ char *new_id; ++ if (type == IF_IDE || type == IF_SCSI) { + mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd"; +- if (max_devs) +- snprintf(dinfo->id, 32, "%s%i%s%i", +- if_name[type], bus_id, mediastr, unit_id); +- else +- snprintf(dinfo->id, 32, "%s%s%i", +- if_name[type], mediastr, unit_id); ++ } ++ if (max_devs) { ++ new_id = g_strdup_printf("%s%i%s%i", if_name[type], bus_id, ++ mediastr, unit_id); ++ } else { ++ new_id = g_strdup_printf("%s%s%i", if_name[type], ++ mediastr, unit_id); ++ } ++ qemu_opts_set_id(opts, new_id); + } ++ ++ /* init */ ++ dinfo = g_malloc0(sizeof(*dinfo)); ++ dinfo->id = g_strdup(qemu_opts_id(opts)); + dinfo->bdrv = bdrv_new(dinfo->id); + dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0; + dinfo->bdrv->read_only = ro; +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 13f5e72..f5ebb05 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -139,6 +139,7 @@ void qemu_opts_loc_restore(QemuOpts *opts); + int qemu_opts_set(QemuOptsList *list, const char *id, + const char *name, const char *value); + const char *qemu_opts_id(QemuOpts *opts); ++void qemu_opts_set_id(QemuOpts *opts, char *id); + void qemu_opts_del(QemuOpts *opts); + void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp); + int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 5d686c8..fcbd1b8 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -825,6 +825,12 @@ const char *qemu_opts_id(QemuOpts *opts) + return opts->id; + } + ++/* The id string will be g_free()d by qemu_opts_del */ ++void qemu_opts_set_id(QemuOpts *opts, char *id) ++{ ++ opts->id = id; ++} ++ + void qemu_opts_del(QemuOpts *opts) + { + QemuOpt *opt; +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-Split-up-cache-option.patch b/SOURCES/kvm-blockdev-Split-up-cache-option.patch new file mode 100644 index 0000000..296d2f6 --- /dev/null +++ b/SOURCES/kvm-blockdev-Split-up-cache-option.patch @@ -0,0 +1,133 @@ +From d106c599acad51da2d0eff0d3f87cff867d52f18 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:22 +0200 +Subject: [PATCH 31/38] blockdev: Split up 'cache' option + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-32-git-send-email-kwolf@redhat.com> +Patchwork-id: 54218 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 31/32] blockdev: Split up 'cache' option +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +The old 'cache' option really encodes three different boolean flags into +a cache mode name, without providing all combinations. Make them three +separate options instead and translate the old option to the new ones +for drive_init(). + +The specific boolean options take precedence if the old cache option is +specified as well, so the following options are equivalent: + +-drive file=x,cache=none,cache.no-flush=true +-drive file=x,cache.writeback=true,cache.direct=true,cache.no-flush=true + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 29c4e2b50d95f4a15c3dd62b39f3402f05a34907) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 47 insertions(+), 10 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++---------- + 1 files changed, 47 insertions(+), 10 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 5d4f2f8..8ffed03 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -452,12 +452,15 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + } + } + +- bdrv_flags |= BDRV_O_CACHE_WB; +- if ((buf = qemu_opt_get(opts, "cache")) != NULL) { +- if (bdrv_parse_cache_flags(buf, &bdrv_flags) != 0) { +- error_report("invalid cache option"); +- return NULL; +- } ++ bdrv_flags = 0; ++ if (qemu_opt_get_bool(opts, "cache.writeback", true)) { ++ bdrv_flags |= BDRV_O_CACHE_WB; ++ } ++ if (qemu_opt_get_bool(opts, "cache.direct", false)) { ++ bdrv_flags |= BDRV_O_NOCACHE; ++ } ++ if (qemu_opt_get_bool(opts, "cache.no-flush", true)) { ++ bdrv_flags |= BDRV_O_NO_FLUSH; + } + + #ifdef CONFIG_LINUX_AIO +@@ -740,6 +743,8 @@ static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to) + + DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + { ++ const char *value; ++ + /* Change legacy command line options into QMP ones */ + qemu_opt_rename(all_opts, "iops", "throttling.iops-total"); + qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read"); +@@ -751,6 +756,31 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + + qemu_opt_rename(all_opts, "readonly", "read-only"); + ++ value = qemu_opt_get(all_opts, "cache"); ++ if (value) { ++ int flags = 0; ++ ++ if (bdrv_parse_cache_flags(value, &flags) != 0) { ++ error_report("invalid cache option"); ++ return NULL; ++ } ++ ++ /* Specific options take precedence */ ++ if (!qemu_opt_get(all_opts, "cache.writeback")) { ++ qemu_opt_set_bool(all_opts, "cache.writeback", ++ !!(flags & BDRV_O_CACHE_WB)); ++ } ++ if (!qemu_opt_get(all_opts, "cache.direct")) { ++ qemu_opt_set_bool(all_opts, "cache.direct", ++ !!(flags & BDRV_O_NOCACHE)); ++ } ++ if (!qemu_opt_get(all_opts, "cache.no-flush")) { ++ qemu_opt_set_bool(all_opts, "cache.no-flush", ++ !!(flags & BDRV_O_NO_FLUSH)); ++ } ++ qemu_opt_unset(all_opts, "cache"); ++ } ++ + return blockdev_init(all_opts, block_default_type); + } + +@@ -1674,10 +1704,17 @@ QemuOptsList qemu_common_drive_opts = { + .type = QEMU_OPT_STRING, + .help = "discard operation (ignore/off, unmap/on)", + },{ +- .name = "cache", +- .type = QEMU_OPT_STRING, +- .help = "host cache usage (none, writeback, writethrough, " +- "directsync, unsafe)", ++ .name = "cache.writeback", ++ .type = QEMU_OPT_BOOL, ++ .help = "enables writeback mode for any caches", ++ },{ ++ .name = "cache.direct", ++ .type = QEMU_OPT_BOOL, ++ .help = "enables use of O_DIRECT (bypass the host page cache)", ++ },{ ++ .name = "cache.no-flush", ++ .type = QEMU_OPT_BOOL, ++ .help = "ignore any flush requests for the device", + },{ + .name = "aio", + .type = QEMU_OPT_STRING, +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-blockdev-add-QMP-command.patch b/SOURCES/kvm-blockdev-blockdev-add-QMP-command.patch new file mode 100644 index 0000000..4b378c9 --- /dev/null +++ b/SOURCES/kvm-blockdev-blockdev-add-QMP-command.patch @@ -0,0 +1,422 @@ +From 0404a8f41dd2d4b7a76bdf07dac6b267adf694cb Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:01 +0100 +Subject: [PATCH 48/87] blockdev: 'blockdev-add' QMP command + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-8-git-send-email-kwolf@redhat.com> +Patchwork-id: 55386 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 07/24] blockdev: 'blockdev-add' QMP command +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +For examples see the changes to qmp-commands.hx. + +Signed-off-by: Kevin Wolf +(cherry picked from commit d26c9a15738147a8dccc451c6f6d1ddc2305713d) + +Conflicts: + qapi-schema.json + qmp-commands.hx + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 57 ++++++++++++++ + qapi-schema.json | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + qmp-commands.hx | 55 +++++++++++++ + 3 files changed, 348 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 57 +++++++++++++ + qapi-schema.json | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + qmp-commands.hx | 55 +++++++++++++ + 3 files changed, 348 insertions(+), 0 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index e379a91..d4f66db 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -38,6 +38,8 @@ + #include "qemu/option.h" + #include "qemu/config-file.h" + #include "qapi/qmp/types.h" ++#include "qapi-visit.h" ++#include "qapi/qmp-output-visitor.h" + #include "sysemu/sysemu.h" + #include "block/block_int.h" + #include "qmp-commands.h" +@@ -1656,6 +1658,61 @@ void qmp_block_job_complete(const char *device, Error **errp) + block_job_complete(job, errp); + } + ++void qmp_blockdev_add(BlockdevOptions *options, Error **errp) ++{ ++ QmpOutputVisitor *ov = qmp_output_visitor_new(); ++ QObject *obj; ++ QDict *qdict; ++ DriveInfo *dinfo; ++ Error *local_err = NULL; ++ ++ /* Require an ID in the top level */ ++ if (!options->has_id) { ++ error_setg(errp, "Block device needs an ID"); ++ goto fail; ++ } ++ ++ /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with ++ * cache.direct=false instead of silently switching to aio=threads, except ++ * if called from drive_init. ++ * ++ * For now, simply forbidding the combination for all drivers will do. */ ++ if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) { ++ bool direct = options->cache->has_direct && options->cache->direct; ++ if (!options->has_cache && !direct) { ++ error_setg(errp, "aio=native requires cache.direct=true"); ++ goto fail; ++ } ++ } ++ ++ visit_type_BlockdevOptions(qmp_output_get_visitor(ov), ++ &options, NULL, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ goto fail; ++ } ++ ++ obj = qmp_output_get_qobject(ov); ++ qdict = qobject_to_qdict(obj); ++ ++ qdict_flatten(qdict); ++ ++ QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ goto fail; ++ } ++ ++ dinfo = blockdev_init(opts, IF_NONE); ++ if (!dinfo) { ++ error_setg(errp, "Could not open image"); ++ goto fail; ++ } ++ ++fail: ++ qmp_output_visitor_cleanup(ov); ++} ++ + static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs) + { + BlockJobInfoList **prev = opaque; +diff --git a/qapi-schema.json b/qapi-schema.json +index 12a360a..32b41b0 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -3674,3 +3674,239 @@ + '*cpuid-input-ecx': 'int', + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } ++ ++ ++## ++# @BlockdevDiscardOptions ++# ++# Determines how to handle discard requests. ++# ++# @ignore: Ignore the request ++# @unmap: Forward as an unmap request ++# ++# Since: 1.7 ++## ++{ 'enum': 'BlockdevDiscardOptions', ++ 'data': [ 'ignore', 'unmap' ] } ++ ++## ++# @BlockdevAioOptions ++# ++# Selects the AIO backend to handle I/O requests ++# ++# @threads: Use qemu's thread pool ++# @native: Use native AIO backend (only Linux and Windows) ++# ++# Since: 1.7 ++## ++{ 'enum': 'BlockdevAioOptions', ++ 'data': [ 'threads', 'native' ] } ++ ++## ++# @BlockdevCacheOptions ++# ++# Includes cache-related options for block devices ++# ++# @writeback: #optional enables writeback mode for any caches (default: true) ++# @direct: #optional enables use of O_DIRECT (bypass the host page cache; ++# default: false) ++# @no-flush: #optional ignore any flush requests for the device (default: ++# false) ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevCacheOptions', ++ 'data': { '*writeback': 'bool', ++ '*direct': 'bool', ++ '*no-flush': 'bool' } } ++ ++## ++# @BlockdevOptionsBase ++# ++# Options that are available for all block devices, independent of the block ++# driver. ++# ++# @driver: block driver name ++# @id: #optional id by which the new block device can be referred to. ++# This is a required option on the top level of blockdev-add, and ++# currently not allowed on any other level. ++# @discard: #optional discard-related options (default: ignore) ++# @cache: #optional cache-related options ++# @aio: #optional AIO backend (default: threads) ++# @rerror: #optional how to handle read errors on the device ++# (default: report) ++# @werror: #optional how to handle write errors on the device ++# (default: enospc) ++# @read-only: #optional whether the block device should be read-only ++# (default: false) ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsBase', ++ 'data': { 'driver': 'str', ++ '*id': 'str', ++ '*discard': 'BlockdevDiscardOptions', ++ '*cache': 'BlockdevCacheOptions', ++ '*aio': 'BlockdevAioOptions', ++ '*rerror': 'BlockdevOnError', ++ '*werror': 'BlockdevOnError', ++ '*read-only': 'bool' } } ++ ++## ++# @BlockdevOptionsFile ++# ++# Driver specific block device options for the file backend and similar ++# protocols. ++# ++# @filename: path to the image file ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsFile', ++ 'data': { 'filename': 'str' } } ++ ++## ++# @BlockdevOptionsVVFAT ++# ++# Driver specific block device options for the vvfat protocol. ++# ++# @dir: directory to be exported as FAT image ++# @fat-type: #optional FAT type: 12, 16 or 32 ++# @floppy: #optional whether to export a floppy image (true) or ++# partitioned hard disk (false; default) ++# @rw: #optional whether to allow write operations (default: false) ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsVVFAT', ++ 'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool', ++ '*rw': 'bool' } } ++ ++## ++# @BlockdevOptionsGenericFormat ++# ++# Driver specific block device options for image format that have no option ++# besides their data source. ++# ++# @file: reference to or definition of the data source block device ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsGenericFormat', ++ 'data': { 'file': 'BlockdevRef' } } ++ ++## ++# @BlockdevOptionsGenericCOWFormat ++# ++# Driver specific block device options for image format that have no option ++# besides their data source and an optional backing file. ++# ++# @backing: #optional reference to or definition of the backing file block ++# device (if missing, taken from the image file content). It is ++# allowed to pass an empty string here in order to disable the ++# default backing file. ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsGenericCOWFormat', ++ 'base': 'BlockdevOptionsGenericFormat', ++ 'data': { '*backing': 'BlockdevRef' } } ++ ++## ++# @BlockdevOptionsQcow2 ++# ++# Driver specific block device options for qcow2. ++# ++# @lazy-refcounts: #optional whether to enable the lazy refcounts ++# feature (default is taken from the image file) ++# ++# @pass-discard-request: #optional whether discard requests to the qcow2 ++# device should be forwarded to the data source ++# ++# @pass-discard-snapshot: #optional whether discard requests for the data source ++# should be issued when a snapshot operation (e.g. ++# deleting a snapshot) frees clusters in the qcow2 file ++# ++# @pass-discard-other: #optional whether discard requests for the data source ++# should be issued on other occasions where a cluster ++# gets freed ++# ++# Since: 1.7 ++## ++{ 'type': 'BlockdevOptionsQcow2', ++ 'base': 'BlockdevOptionsGenericCOWFormat', ++ 'data': { '*lazy-refcounts': 'bool', ++ '*pass-discard-request': 'bool', ++ '*pass-discard-snapshot': 'bool', ++ '*pass-discard-other': 'bool' } } ++ ++## ++# @BlockdevOptions ++# ++# Options for creating a block device. ++# ++# Since: 1.7 ++## ++{ 'union': 'BlockdevOptions', ++ 'base': 'BlockdevOptionsBase', ++ 'discriminator': 'driver', ++ 'data': { ++ 'file': 'BlockdevOptionsFile', ++ 'http': 'BlockdevOptionsFile', ++ 'https': 'BlockdevOptionsFile', ++ 'ftp': 'BlockdevOptionsFile', ++ 'ftps': 'BlockdevOptionsFile', ++ 'tftp': 'BlockdevOptionsFile', ++# TODO gluster: Wait for structured options ++# TODO iscsi: Wait for structured options ++# TODO nbd: Should take InetSocketAddress for 'host'? ++# TODO rbd: Wait for structured options ++# TODO sheepdog: Wait for structured options ++# TODO ssh: Should take InetSocketAddress for 'host'? ++ 'vvfat': 'BlockdevOptionsVVFAT', ++ ++# TODO blkdebug: Wait for structured options ++# TODO blkverify: Wait for structured options ++ ++ 'bochs': 'BlockdevOptionsGenericFormat', ++ 'cloop': 'BlockdevOptionsGenericFormat', ++ 'cow': 'BlockdevOptionsGenericCOWFormat', ++ 'dmg': 'BlockdevOptionsGenericFormat', ++ 'parallels': 'BlockdevOptionsGenericFormat', ++ 'qcow': 'BlockdevOptionsGenericCOWFormat', ++ 'qcow2': 'BlockdevOptionsQcow2', ++ 'qed': 'BlockdevOptionsGenericCOWFormat', ++ 'raw': 'BlockdevOptionsGenericFormat', ++ 'vdi': 'BlockdevOptionsGenericFormat', ++ 'vhdx': 'BlockdevOptionsGenericFormat', ++ 'vmdk': 'BlockdevOptionsGenericCOWFormat', ++ 'vpc': 'BlockdevOptionsGenericFormat' ++ } } ++ ++## ++# @BlockdevRef ++# ++# Reference to a block device. ++# ++# @definition: defines a new block device inline ++# @reference: references the ID of an existing block device. An ++# empty string means that no block device should be ++# referenced. ++# ++# Since: 1.7 ++## ++{ 'union': 'BlockdevRef', ++ 'discriminator': {}, ++ 'data': { 'definition': 'BlockdevOptions', ++ 'reference': 'str' } } ++ ++## ++# @blockdev-add: ++# ++# Creates a new block device. ++# ++# @options: block device options for the new device ++# ++# Since: 1.7 ++## ++{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } } +diff --git a/qmp-commands.hx b/qmp-commands.hx +index e40d54d..d1f6f8b 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -2941,3 +2941,58 @@ Example: + <- { "return": {} } + + EQMP ++ ++ { ++ .name = "blockdev-add", ++ .args_type = "options:q", ++ .mhandler.cmd_new = qmp_marshal_input_blockdev_add, ++ }, ++ ++SQMP ++blockdev-add ++------------ ++ ++Add a block device. ++ ++Arguments: ++ ++- "options": block driver options ++ ++Example (1): ++ ++-> { "execute": "blockdev-add", ++ "arguments": { "options" : { "driver": "qcow2", ++ "file": { "driver": "file", ++ "filename": "test.qcow2" } } } } ++<- { "return": {} } ++ ++Example (2): ++ ++-> { "execute": "blockdev-add", ++ "arguments": { ++ "options": { ++ "driver": "qcow2", ++ "id": "my_disk", ++ "discard": "unmap", ++ "cache": { ++ "direct": true, ++ "writeback": true ++ }, ++ "file": { ++ "driver": "file", ++ "filename": "/tmp/test.qcow2" ++ }, ++ "backing": { ++ "driver": "raw", ++ "file": { ++ "driver": "file", ++ "filename": "/dev/fdset/4" ++ } ++ } ++ } ++ } ++ } ++ ++<- { "return": {} } ++ ++EQMP +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-blockdev_init-error-conversion.patch b/SOURCES/kvm-blockdev-blockdev_init-error-conversion.patch new file mode 100644 index 0000000..b2b2c8f --- /dev/null +++ b/SOURCES/kvm-blockdev-blockdev_init-error-conversion.patch @@ -0,0 +1,205 @@ +From 8e44095beac9a5c6da5e91339c5cf7746afaa623 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 7 Nov 2013 12:53:07 +0100 +Subject: [PATCH 61/87] blockdev: blockdev_init() error conversion + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-21-git-send-email-kwolf@redhat.com> +Patchwork-id: 55399 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 20/24] blockdev: blockdev_init() error conversion +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +This gives us meaningful error messages for the blockdev-add QMP +command. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit b681072d2005911b79835d2a6af208eba3983a48) + +Conflicts: + blockdev.c + +Conflict caused by do_check_io_limits(), which has been replaced by +check_throttle_config() in upstream (commit cc0681c4 'block: Enable the +new throttling code in the block layer.') + +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 56 +++++++++++++++++++++++++++++++------------------------- + 1 files changed, 31 insertions(+), 25 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index cbf01eb..a248480 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -275,7 +275,7 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo) + } + #endif + +-static int parse_block_error_action(const char *buf, bool is_read) ++static int parse_block_error_action(const char *buf, bool is_read, Error **errp) + { + if (!strcmp(buf, "ignore")) { + return BLOCKDEV_ON_ERROR_IGNORE; +@@ -286,8 +286,8 @@ static int parse_block_error_action(const char *buf, bool is_read) + } else if (!strcmp(buf, "report")) { + return BLOCKDEV_ON_ERROR_REPORT; + } else { +- error_report("'%s' invalid %s error action", +- buf, is_read ? "read" : "write"); ++ error_setg(errp, "'%s' invalid %s error action", ++ buf, is_read ? "read" : "write"); + return -1; + } + } +@@ -328,7 +328,8 @@ typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType; + + /* Takes the ownership of bs_opts */ + static DriveInfo *blockdev_init(QDict *bs_opts, +- BlockInterfaceType type) ++ BlockInterfaceType type, ++ Error **errp) + { + const char *buf; + const char *file = NULL; +@@ -352,15 +353,13 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + id = qdict_get_try_str(bs_opts, "id"); + opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error); + if (error_is_set(&error)) { +- qerror_report_err(error); +- error_free(error); ++ error_propagate(errp, error); + return NULL; + } + + qemu_opts_absorb_qdict(opts, bs_opts, &error); + if (error_is_set(&error)) { +- qerror_report_err(error); +- error_free(error); ++ error_propagate(errp, error); + return NULL; + } + +@@ -380,7 +379,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + + if ((buf = qemu_opt_get(opts, "discard")) != NULL) { + if (bdrv_parse_discard_flags(buf, &bdrv_flags) != 0) { +- error_report("invalid discard option"); ++ error_setg(errp, "invalid discard option"); + return NULL; + } + } +@@ -403,7 +402,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + } else if (!strcmp(buf, "threads")) { + /* this is the default */ + } else { +- error_report("invalid aio option"); ++ error_setg(errp, "invalid aio option"); + return NULL; + } + } +@@ -419,7 +418,7 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + + drv = bdrv_find_whitelisted_format(buf, ro); + if (!drv) { +- error_report("'%s' invalid format", buf); ++ error_setg(errp, "'%s' invalid format", buf); + return NULL; + } + } +@@ -439,20 +438,20 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + qemu_opt_get_number(opts, "throttling.iops-write", 0); + + if (!do_check_io_limits(&io_limits, &error)) { +- error_report("%s", error_get_pretty(error)); +- error_free(error); ++ error_propagate(errp, error); + return NULL; + } + + on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { + if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { +- error_report("werror is not supported by this bus type"); ++ error_setg(errp, "werror is not supported by this bus type"); + return NULL; + } + +- on_write_error = parse_block_error_action(buf, 0); +- if (on_write_error < 0) { ++ on_write_error = parse_block_error_action(buf, 0, &error); ++ if (error_is_set(&error)) { ++ error_propagate(errp, error); + return NULL; + } + } +@@ -464,8 +463,9 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + return NULL; + } + +- on_read_error = parse_block_error_action(buf, 1); +- if (on_read_error < 0) { ++ on_read_error = parse_block_error_action(buf, 1, &error); ++ if (error_is_set(&error)) { ++ error_propagate(errp, error); + return NULL; + } + } +@@ -515,8 +515,9 @@ static DriveInfo *blockdev_init(QDict *bs_opts, + ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error); + + if (ret < 0) { +- error_report("could not open disk image %s: %s", +- file ?: dinfo->id, error_get_pretty(error)); ++ error_setg(errp, "could not open disk image %s: %s", ++ file ?: dinfo->id, error_get_pretty(error)); ++ error_free(error); + goto err; + } + +@@ -852,9 +853,15 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + + /* Actual block device init: Functionality shared with blockdev-add */ +- dinfo = blockdev_init(bs_opts, type); ++ dinfo = blockdev_init(bs_opts, type, &local_err); + if (dinfo == NULL) { ++ if (error_is_set(&local_err)) { ++ qerror_report_err(local_err); ++ error_free(local_err); ++ } + goto fail; ++ } else { ++ assert(!error_is_set(&local_err)); + } + + /* Set legacy DriveInfo fields */ +@@ -1745,7 +1752,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + QmpOutputVisitor *ov = qmp_output_visitor_new(); + QObject *obj; + QDict *qdict; +- DriveInfo *dinfo; + Error *local_err = NULL; + + /* Require an ID in the top level */ +@@ -1779,9 +1785,9 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp) + + qdict_flatten(qdict); + +- dinfo = blockdev_init(qdict, IF_NONE); +- if (!dinfo) { +- error_setg(errp, "Could not open image"); ++ blockdev_init(qdict, IF_NONE, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); + goto fail; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-do-not-default-cache.no-flush-to-true.patch b/SOURCES/kvm-blockdev-do-not-default-cache.no-flush-to-true.patch new file mode 100644 index 0000000..8a7f5a0 --- /dev/null +++ b/SOURCES/kvm-blockdev-do-not-default-cache.no-flush-to-true.patch @@ -0,0 +1,48 @@ +From ae3974ef64713d94dcb2766e3d8f89edc1a01c0c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 23 Sep 2013 17:08:01 +0200 +Subject: [PATCH 03/29] blockdev: do not default cache.no-flush to true + +RH-Author: Paolo Bonzini +Message-id: <1379956082-3646-2-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54491 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 1/2] blockdev: do not default cache.no-flush to true +Bugzilla: 1009993 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +That's why all my VMs were so fast lately. :) + +This changed in 1.6.0 by mistake in patch 29c4e2b (blockdev: Split up +'cache' option, 2013-07-18). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 1df6fa4bc6754a170cf511a78e2e6fef84eb5228) +--- + blockdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 8ffed03..073f553 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -459,7 +459,7 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, + if (qemu_opt_get_bool(opts, "cache.direct", false)) { + bdrv_flags |= BDRV_O_NOCACHE; + } +- if (qemu_opt_get_bool(opts, "cache.no-flush", true)) { ++ if (qemu_opt_get_bool(opts, "cache.no-flush", false)) { + bdrv_flags |= BDRV_O_NO_FLUSH; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-drop-redundant-proto_drv-check.patch b/SOURCES/kvm-blockdev-drop-redundant-proto_drv-check.patch new file mode 100644 index 0000000..9a3ac53 --- /dev/null +++ b/SOURCES/kvm-blockdev-drop-redundant-proto_drv-check.patch @@ -0,0 +1,104 @@ +From d9420445fe0b78de91dc8615a61b973ed64e4f78 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:27:57 +0200 +Subject: [PATCH 06/38] blockdev: drop redundant proto_drv check + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-7-git-send-email-kwolf@redhat.com> +Patchwork-id: 54193 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 06/32] blockdev: drop redundant proto_drv check +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Stefan Hajnoczi + +Bugzilla: 1005818 + +It is not necessary to check that we can find a protocol block driver +since we create or open the image file. This produces the error that we +need anyway. + +Besides, the QERR_INVALID_BLOCK_FORMAT is inappropriate since the +protocol is incorrect rather than the format. + +Also drop an empty line between bdrv_open() and checking its return +value. This may be due to copy-pasting from earlier code that performed +other operations before handling errors. + +Reported-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Wenchao Xia +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit cb78466ef60ccf707a6f38a1294c435b65a828e0) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 15 --------------- + 1 file changed, 15 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 15 --------------- + 1 files changed, 0 insertions(+), 15 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index b8521c7..1f405c9 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -818,7 +818,6 @@ typedef struct ExternalSnapshotStates { + static void external_snapshot_prepare(BlkTransactionStates *common, + Error **errp) + { +- BlockDriver *proto_drv; + BlockDriver *drv; + int flags, ret; + Error *local_err = NULL; +@@ -874,12 +873,6 @@ static void external_snapshot_prepare(BlkTransactionStates *common, + + flags = states->old_bs->open_flags; + +- proto_drv = bdrv_find_protocol(new_image_file); +- if (!proto_drv) { +- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); +- return; +- } +- + /* create new image w/backing file */ + if (mode != NEW_IMAGE_MODE_EXISTING) { + bdrv_img_create(new_image_file, format, +@@ -1372,7 +1365,6 @@ void qmp_drive_mirror(const char *device, const char *target, + { + BlockDriverState *bs; + BlockDriverState *source, *target_bs; +- BlockDriver *proto_drv; + BlockDriver *drv = NULL; + Error *local_err = NULL; + int flags; +@@ -1440,12 +1432,6 @@ void qmp_drive_mirror(const char *device, const char *target, + sync = MIRROR_SYNC_MODE_FULL; + } + +- proto_drv = bdrv_find_protocol(target); +- if (!proto_drv) { +- error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); +- return; +- } +- + bdrv_get_geometry(bs, &size); + size *= 512; + if (sync == MIRROR_SYNC_MODE_FULL && mode != NEW_IMAGE_MODE_EXISTING) { +@@ -1480,7 +1466,6 @@ void qmp_drive_mirror(const char *device, const char *target, + */ + target_bs = bdrv_new(""); + ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv); +- + if (ret < 0) { + bdrv_delete(target_bs); + error_set(errp, QERR_OPEN_FILE_FAILED, target); +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-fix-cdrom-read_only-flag.patch b/SOURCES/kvm-blockdev-fix-cdrom-read_only-flag.patch new file mode 100644 index 0000000..19a62d1 --- /dev/null +++ b/SOURCES/kvm-blockdev-fix-cdrom-read_only-flag.patch @@ -0,0 +1,72 @@ +From b760a59d212007cbe0276d6027fb24809f1330d9 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:16 +0100 +Subject: [PATCH 63/87] blockdev: fix cdrom read_only flag + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-23-git-send-email-kwolf@redhat.com> +Patchwork-id: 55401 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 22/24] blockdev: fix cdrom read_only flag +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +From: Fam Zheng + +Since 0ebd24e0, cdrom doesn't have read-only on by default, which will +error out when using an read only image. Fix it by setting the default +value when parsing opts. + +Reported-by: Edivaldo de Araujo Pereira +Signed-off-by: Fam Zheng + +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit a7fdbcf0e6e52d935ebff6d849fe4b5473e5860d) + +Signed-off-by: Kevin Wolf +--- + blockdev.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 7 ++++--- + 1 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index a248480..a9c5d32 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -626,7 +626,8 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + int cyls, heads, secs, translation; + int max_devs, bus_id, unit_id, index; + const char *devaddr; +- bool read_only, copy_on_read; ++ bool read_only = false; ++ bool copy_on_read; + Error *local_err = NULL; + + /* Change legacy command line options into QMP ones */ +@@ -691,7 +692,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + media = MEDIA_DISK; + } else if (!strcmp(value, "cdrom")) { + media = MEDIA_CDROM; +- qdict_put(bs_opts, "read-only", qstring_from_str("on")); ++ read_only = true; + } else { + error_report("'%s' invalid media", value); + goto fail; +@@ -699,7 +700,7 @@ DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type) + } + + /* copy-on-read is disabled with a warning for read-only devices */ +- read_only = qemu_opt_get_bool(legacy_opts, "read-only", false); ++ read_only |= qemu_opt_get_bool(legacy_opts, "read-only", false); + copy_on_read = qemu_opt_get_bool(legacy_opts, "copy-on-read", false); + + if (read_only && copy_on_read) { +-- +1.7.1 + diff --git a/SOURCES/kvm-blockdev-use-error_setg_file_open.patch b/SOURCES/kvm-blockdev-use-error_setg_file_open.patch new file mode 100644 index 0000000..0c57b4e --- /dev/null +++ b/SOURCES/kvm-blockdev-use-error_setg_file_open.patch @@ -0,0 +1,69 @@ +From 4aeb6d14385793a46b11d4d129bbad6c9fe9132b Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:26 +0100 +Subject: [PATCH 07/29] blockdev: use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-4-git-send-email-lersek@redhat.com> +Patchwork-id: 55193 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/8] blockdev: use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Reviewed-by: Stefan Hajnoczi +Acked-by: Kevin Wolf +(cherry picked from commit 0eef407c7b4130d13138c1f75d9975165433f654) +Signed-off-by: Laszlo Ersek +--- + blockdev.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + blockdev.c | 11 +++++++---- + 1 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/blockdev.c b/blockdev.c +index 073f553..f65aff4 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -950,7 +950,7 @@ static void external_snapshot_prepare(BlkTransactionStates *common, + ret = bdrv_open(states->new_bs, new_image_file, NULL, + flags | BDRV_O_NO_BACKING, drv); + if (ret != 0) { +- error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); ++ error_setg_file_open(errp, -ret, new_image_file); + } + } + +@@ -1113,8 +1113,11 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename, + int bdrv_flags, BlockDriver *drv, + const char *password, Error **errp) + { +- if (bdrv_open(bs, filename, NULL, bdrv_flags, drv) < 0) { +- error_set(errp, QERR_OPEN_FILE_FAILED, filename); ++ int ret; ++ ++ ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv); ++ if (ret < 0) { ++ error_setg_file_open(errp, -ret, filename); + return; + } + +@@ -1526,7 +1529,7 @@ void qmp_drive_mirror(const char *device, const char *target, + ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv); + if (ret < 0) { + bdrv_delete(target_bs); +- error_set(errp, QERR_OPEN_FILE_FAILED, target); ++ error_setg_file_open(errp, -ret, target); + return; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-boot-order-test-New-covering-just-PC-for-now.patch b/SOURCES/kvm-boot-order-test-New-covering-just-PC-for-now.patch new file mode 100644 index 0000000..082b01c --- /dev/null +++ b/SOURCES/kvm-boot-order-test-New-covering-just-PC-for-now.patch @@ -0,0 +1,138 @@ +From 99dd65105a5f7048d231e311b55995ef41f37278 Mon Sep 17 00:00:00 2001 +Message-Id: <99dd65105a5f7048d231e311b55995ef41f37278.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:20 +0200 +Subject: [PATCH 10/14] boot-order-test: New; covering just PC for now + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-11-git-send-email-armbru@redhat.com> +Patchwork-id: 54563 +O-Subject: [PATCH 7.0 qemu-kvm 10/10] boot-order-test: New; covering just PC for now +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Message-id: 1372254743-15808-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit edbd790d20cf19d039dfe431aaf0973a9e0afa8f) +--- + tests/Makefile | 2 ++ + tests/boot-order-test.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 75 insertions(+) + create mode 100644 tests/boot-order-test.c + +Signed-off-by: Michal Novotny +--- + tests/Makefile | 2 ++ + tests/boot-order-test.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 75 insertions(+) + create mode 100644 tests/boot-order-test.c + +diff --git a/tests/Makefile b/tests/Makefile +index c107489..394e029 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -54,6 +54,7 @@ gcov-files-i386-y = hw/fdc.c + check-qtest-i386-y += tests/ide-test$(EXESUF) + check-qtest-i386-y += tests/hd-geo-test$(EXESUF) + gcov-files-i386-y += hw/hd-geometry.c ++check-qtest-i386-y += tests/boot-order-test$(EXESUF) + check-qtest-i386-y += tests/rtc-test$(EXESUF) + check-qtest-i386-y += tests/i440fx-test$(EXESUF) + check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) +@@ -130,6 +131,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o + tests/fdc-test$(EXESUF): tests/fdc-test.o + tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y) + tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o ++tests/boot-order-test$(EXESUF): tests/boot-order-test.o + tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) + tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) + tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) +diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c +new file mode 100644 +index 0000000..447be31 +--- /dev/null ++++ b/tests/boot-order-test.c +@@ -0,0 +1,73 @@ ++/* ++ * Boot order test cases. ++ * ++ * Copyright (c) 2013 Red Hat Inc. ++ * ++ * Authors: ++ * Markus Armbruster , ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++ ++#include ++#include "libqtest.h" ++ ++static void test_pc_cmos_byte(int reg, int expected) ++{ ++ int actual; ++ ++ outb(0x70, reg); ++ actual = inb(0x71); ++ g_assert_cmphex(actual, ==, expected); ++} ++ ++static void test_pc_cmos(uint8_t boot1, uint8_t boot2) ++{ ++ test_pc_cmos_byte(0x38, boot1); ++ test_pc_cmos_byte(0x3d, boot2); ++} ++ ++static void test_pc_with_args(const char *test_args, ++ uint8_t boot1, uint8_t boot2, ++ uint8_t reboot1, uint8_t reboot2) ++{ ++ char *args = g_strdup_printf("-nodefaults -display none %s", test_args); ++ ++ qtest_start(args); ++ test_pc_cmos(boot1, boot2); ++ qmp("{ 'execute': 'system_reset' }"); ++ /* ++ * system_reset only requests reset. We get a RESET event after ++ * the actual reset completes. Need to wait for that. ++ */ ++ qmp(""); /* HACK: wait for event */ ++ test_pc_cmos(reboot1, reboot2); ++ qtest_quit(global_qtest); ++ g_free(args); ++} ++ ++static void test_pc_boot_order(void) ++{ ++ test_pc_with_args("", 0x30, 0x12, 0x30, 0x12); ++ test_pc_with_args("-no-fd-bootchk", 0x31, 0x12, 0x31, 0x12); ++ test_pc_with_args("-boot c", 0, 0x02, 0, 0x02); ++ test_pc_with_args("-boot nda", 0x10, 0x34, 0x10, 0x34); ++ test_pc_with_args("-boot order=", 0, 0, 0, 0); ++ test_pc_with_args("-boot order= -boot order=c", 0, 0x02, 0, 0x02); ++ test_pc_with_args("-boot once=a", 0, 0x01, 0x30, 0x12); ++ test_pc_with_args("-boot once=a -no-fd-bootchk", 0x01, 0x01, 0x31, 0x12); ++ test_pc_with_args("-boot once=a,order=c", 0, 0x01, 0, 0x02); ++ test_pc_with_args("-boot once=d -boot order=nda", 0, 0x03, 0x10, 0x34); ++ test_pc_with_args("-boot once=a -boot once=b -boot once=c", ++ 0, 0x02, 0x30, 0x12); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ g_test_init(&argc, &argv, NULL); ++ ++ qtest_add_func("boot-order/pc", test_pc_boot_order); ++ ++ return g_test_run(); ++} +-- +1.7.11.7 + diff --git a/SOURCES/kvm-char-io_channel_send-don-t-lose-written-bytes.patch b/SOURCES/kvm-char-io_channel_send-don-t-lose-written-bytes.patch new file mode 100644 index 0000000..c412fc6 --- /dev/null +++ b/SOURCES/kvm-char-io_channel_send-don-t-lose-written-bytes.patch @@ -0,0 +1,93 @@ +From ddc3793752ae726e761173ce214ab895b936d15a Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 19 Jul 2013 13:05:22 +0200 +Subject: char: io_channel_send: don't lose written bytes + +RH-Author: Laszlo Ersek +Message-id: <1374239123-4841-2-git-send-email-lersek@redhat.com> +Patchwork-id: 52615 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/2] char: io_channel_send: don't lose written bytes +Bugzilla: 970047 +RH-Acked-by: Amit Shah +RH-Acked-by: Markus Armbruster +RH-Acked-by: Luiz Capitulino + +The g_io_channel_write_chars() documentation states, + + bytes_written: The number of bytes written. This can be nonzero even if + the return value is not G_IO_STATUS_NORMAL. [...] + +io_channel_send() could lose such bytes before. + +Furthermore, the (status == G_IO_STATUS_EOF) condition used to evaluate to +constant false whenever it was reached. When that condition actually held, +it always led to -1 / EINVAL. This patch (almost) distinguishes +G_IO_STATUS_EOF only when no bytes have been written, and then treats it +as an error. + +Signed-off-by: Laszlo Ersek +Reviewed-by: Amit Shah +Reviewed-by: Anthony Liguori +Message-id: 1373998781-29561-2-git-send-email-lersek@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit ac8c26f633b01bb32cdf347f9dbd5a80c6712925) + +diff --git a/qemu-char.c b/qemu-char.c +index efe706d..c01deae 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -722,35 +722,32 @@ static GIOChannel *io_channel_from_socket(int fd) + + static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) + { +- GIOStatus status; +- size_t offset; ++ size_t offset = 0; ++ GIOStatus status = G_IO_STATUS_NORMAL; + +- offset = 0; +- while (offset < len) { +- gsize bytes_written; ++ while (offset < len && status == G_IO_STATUS_NORMAL) { ++ gsize bytes_written = 0; + + status = g_io_channel_write_chars(fd, buf + offset, len - offset, + &bytes_written, NULL); +- if (status != G_IO_STATUS_NORMAL) { +- if (status == G_IO_STATUS_AGAIN) { +- /* If we've written any data, return a partial write. */ +- if (offset) { +- break; +- } +- errno = EAGAIN; +- } else { +- errno = EINVAL; +- } +- +- return -1; +- } else if (status == G_IO_STATUS_EOF) { +- break; +- } +- + offset += bytes_written; + } + +- return offset; ++ if (offset > 0) { ++ return offset; ++ } ++ switch (status) { ++ case G_IO_STATUS_NORMAL: ++ g_assert(len == 0); ++ return 0; ++ case G_IO_STATUS_AGAIN: ++ errno = EAGAIN; ++ return -1; ++ default: ++ break; ++ } ++ errno = EINVAL; ++ return -1; + } + + #ifndef _WIN32 diff --git a/SOURCES/kvm-char-move-backends-io-watch-tag-to-CharDriverState.patch b/SOURCES/kvm-char-move-backends-io-watch-tag-to-CharDriverState.patch new file mode 100644 index 0000000..a58b868 --- /dev/null +++ b/SOURCES/kvm-char-move-backends-io-watch-tag-to-CharDriverState.patch @@ -0,0 +1,248 @@ +From 418c81950cabb2c5b51060476396ddb0897ee2e7 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Tue, 8 Oct 2013 06:13:05 +0200 +Subject: [PATCH 06/11] char: move backends' io watch tag to CharDriverState + +RH-Author: Amit Shah +Message-id: <425ec481c2ad94003f59ce6febaa1143fcf853e5.1381210228.git.amit.shah@redhat.com> +Patchwork-id: 54727 +O-Subject: [RHEL7 qemu-kvm PATCH 1/3] char: move backends' io watch tag to CharDriverState +Bugzilla: 1007222 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Michael S. Tsirkin + +All the backends implement an io watcher tag for callbacks. Move it to +CharDriverState from each backend's struct to make accessing the tag from +backend-neutral functions easier. + +This will be used later to cancel a callback on chardev detach from a +frontend. + +CC: +Reviewed-by: Gerd Hoffmann +Signed-off-by: Amit Shah +--- + include/sysemu/char.h | 1 + + qemu-char.c | 77 ++++++++++++++++++++++++++------------------------- + 2 files changed, 40 insertions(+), 38 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/sysemu/char.h | 1 + + qemu-char.c | 77 +++++++++++++++++++++++++------------------------ + 2 files changed, 40 insertions(+), 38 deletions(-) + +diff --git a/include/sysemu/char.h b/include/sysemu/char.h +index ac2aaaf..f0ed280 100644 +--- a/include/sysemu/char.h ++++ b/include/sysemu/char.h +@@ -78,6 +78,7 @@ struct CharDriverState { + int explicit_be_open; + int avail_connections; + int is_mux; ++ guint fd_in_tag; + QemuOpts *opts; + QTAILQ_ENTRY(CharDriverState) next; + }; +diff --git a/qemu-char.c b/qemu-char.c +index 566267a..00cbf88 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -800,7 +800,6 @@ static int io_channel_send(GIOChannel *fd, const void *buf, size_t len) + typedef struct FDCharDriver { + CharDriverState *chr; + GIOChannel *fd_in, *fd_out; +- guint fd_in_tag; + int max_size; + QTAILQ_ENTRY(FDCharDriver) node; + } FDCharDriver; +@@ -832,9 +831,9 @@ static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + status = g_io_channel_read_chars(chan, (gchar *)buf, + len, &bytes_read, NULL); + if (status == G_IO_STATUS_EOF) { +- if (s->fd_in_tag) { +- io_remove_watch_poll(s->fd_in_tag); +- s->fd_in_tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); + return FALSE; +@@ -865,13 +864,14 @@ static void fd_chr_update_read_handler(CharDriverState *chr) + { + FDCharDriver *s = chr->opaque; + +- if (s->fd_in_tag) { +- io_remove_watch_poll(s->fd_in_tag); +- s->fd_in_tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + + if (s->fd_in) { +- s->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, fd_chr_read, chr); ++ chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, ++ fd_chr_read, chr); + } + } + +@@ -879,9 +879,9 @@ static void fd_chr_close(struct CharDriverState *chr) + { + FDCharDriver *s = chr->opaque; + +- if (s->fd_in_tag) { +- io_remove_watch_poll(s->fd_in_tag); +- s->fd_in_tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + + if (s->fd_in) { +@@ -1016,7 +1016,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) + + typedef struct { + GIOChannel *fd; +- guint fd_tag; + int connected; + int read_bytes; + guint timer_tag; +@@ -1131,9 +1130,9 @@ static void pty_chr_state(CharDriverState *chr, int connected) + PtyCharDriver *s = chr->opaque; + + if (!connected) { +- if (s->fd_tag) { +- io_remove_watch_poll(s->fd_tag); +- s->fd_tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + s->connected = 0; + /* (re-)connect poll interval for idle guests: once per second. +@@ -1148,7 +1147,8 @@ static void pty_chr_state(CharDriverState *chr, int connected) + if (!s->connected) { + s->connected = 1; + qemu_chr_be_generic_open(chr); +- s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr); ++ chr->fd_in_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, ++ pty_chr_read, chr); + } + } + } +@@ -1159,9 +1159,9 @@ static void pty_chr_close(struct CharDriverState *chr) + PtyCharDriver *s = chr->opaque; + int fd; + +- if (s->fd_tag) { +- io_remove_watch_poll(s->fd_tag); +- s->fd_tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + fd = g_io_channel_unix_get_fd(s->fd); + g_io_channel_unref(s->fd); +@@ -2169,7 +2169,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) + typedef struct { + int fd; + GIOChannel *chan; +- guint tag; + uint8_t buf[READ_BUF_LEN]; + int bufcnt; + int bufptr; +@@ -2225,9 +2224,9 @@ static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + s->bufcnt = bytes_read; + s->bufptr = s->bufcnt; + if (status != G_IO_STATUS_NORMAL) { +- if (s->tag) { +- io_remove_watch_poll(s->tag); +- s->tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + return FALSE; + } +@@ -2246,22 +2245,23 @@ static void udp_chr_update_read_handler(CharDriverState *chr) + { + NetCharDriver *s = chr->opaque; + +- if (s->tag) { +- io_remove_watch_poll(s->tag); +- s->tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + + if (s->chan) { +- s->tag = io_add_watch_poll(s->chan, udp_chr_read_poll, udp_chr_read, chr); ++ chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll, ++ udp_chr_read, chr); + } + } + + static void udp_chr_close(CharDriverState *chr) + { + NetCharDriver *s = chr->opaque; +- if (s->tag) { +- io_remove_watch_poll(s->tag); +- s->tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + if (s->chan) { + g_io_channel_unref(s->chan); +@@ -2310,7 +2310,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) + typedef struct { + + GIOChannel *chan, *listen_chan; +- guint tag, listen_tag; ++ guint listen_tag; + int fd, listen_fd; + int connected; + int max_size; +@@ -2495,9 +2495,9 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + if (s->listen_chan) { + s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); + } +- if (s->tag) { +- io_remove_watch_poll(s->tag); +- s->tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + g_io_channel_unref(s->chan); + s->chan = NULL; +@@ -2528,7 +2528,8 @@ static void tcp_chr_connect(void *opaque) + + s->connected = 1; + if (s->chan) { +- s->tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, tcp_chr_read, chr); ++ chr->fd_in_tag = io_add_watch_poll(s->chan, tcp_chr_read_poll, ++ tcp_chr_read, chr); + } + qemu_chr_be_generic_open(chr); + } +@@ -2611,9 +2612,9 @@ static void tcp_chr_close(CharDriverState *chr) + { + TCPCharDriver *s = chr->opaque; + if (s->fd >= 0) { +- if (s->tag) { +- io_remove_watch_poll(s->tag); +- s->tag = 0; ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; + } + if (s->chan) { + g_io_channel_unref(s->chan); +-- +1.7.1 + diff --git a/SOURCES/kvm-char-remove-watch-callback-on-chardev-detach-from-fr.patch b/SOURCES/kvm-char-remove-watch-callback-on-chardev-detach-from-fr.patch new file mode 100644 index 0000000..753f372 --- /dev/null +++ b/SOURCES/kvm-char-remove-watch-callback-on-chardev-detach-from-fr.patch @@ -0,0 +1,66 @@ +From dd0ab2d849f8a93fe54a29eedb8a536fbc42fe5d Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Tue, 8 Oct 2013 06:13:07 +0200 +Subject: [PATCH 08/11] char: remove watch callback on chardev detach from frontend + +RH-Author: Amit Shah +Message-id: <0044db8c12053fd38667200f350132d7a3485cde.1381210228.git.amit.shah@redhat.com> +Patchwork-id: 54729 +O-Subject: [RHEL7 qemu-kvm PATCH 3/3] char: remove watch callback on chardev detach from frontend +Bugzilla: 1007222 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Michael S. Tsirkin + +If a frontend device releases the chardev (via unplug), the chr handlers +are set to NULL via qdev's exit callbacks invoking +qemu_chr_add_handlers(). If the chardev had a pending operation, a +callback will be invoked, which will try to access data in the +just-released frontend, causing a segfault. + +Ensure the callbacks are disabled when frontends release chardevs. + +This was seen when a virtio-serial port was unplugged when heavy +guest->host IO was in progress (causing a callback to be registered). +In the window in which the throttling was active, unplugging ports +caused a qemu segfault. + +https://bugzilla.redhat.com/show_bug.cgi?id=985205 + +CC: +Reported-by: Sibiao Luo +Reviewed-by: Gerd Hoffmann +Signed-off-by: Amit Shah +--- + qemu-char.c | 3 +++ + 1 file changed, 3 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 8d46f98..2fb876c 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -195,6 +195,8 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...) + va_end(ap); + } + ++static void remove_fd_in_watch(CharDriverState *chr); ++ + void qemu_chr_add_handlers(CharDriverState *s, + IOCanReadHandler *fd_can_read, + IOReadHandler *fd_read, +@@ -205,6 +207,7 @@ void qemu_chr_add_handlers(CharDriverState *s, + + if (!opaque && !fd_can_read && !fd_read && !fd_event) { + fe_open = 0; ++ remove_fd_in_watch(s); + } else { + fe_open = 1; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-char-use-common-function-to-disable-callbacks-on-cha.patch b/SOURCES/kvm-char-use-common-function-to-disable-callbacks-on-cha.patch new file mode 100644 index 0000000..d7fb5da --- /dev/null +++ b/SOURCES/kvm-char-use-common-function-to-disable-callbacks-on-cha.patch @@ -0,0 +1,174 @@ +From a553f55610d9c5f016aefc8cc2914c769664ef53 Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Tue, 8 Oct 2013 06:13:06 +0200 +Subject: [PATCH 07/11] char: use common function to disable callbacks on chardev close + +RH-Author: Amit Shah +Message-id: <50da0ea80f5257a98f27567ce2bbd987355f795e.1381210228.git.amit.shah@redhat.com> +Patchwork-id: 54728 +O-Subject: [RHEL7 qemu-kvm PATCH 2/3] char: use common function to disable callbacks on chardev close +Bugzilla: 1007222 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Michael S. Tsirkin + +This deduplicates code used a lot of times. + +CC: +Reviewed-by: Gerd Hoffmann +Signed-off-by: Amit Shah +--- + qemu-char.c | 62 +++++++++++++++++++------------------------------------------ + 1 file changed, 19 insertions(+), 43 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 62 ++++++++++++++++++---------------------------------------- + 1 files changed, 19 insertions(+), 43 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 00cbf88..8d46f98 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -727,6 +727,14 @@ static void io_remove_watch_poll(guint tag) + g_source_destroy(&iwp->parent); + } + ++static void remove_fd_in_watch(CharDriverState *chr) ++{ ++ if (chr->fd_in_tag) { ++ io_remove_watch_poll(chr->fd_in_tag); ++ chr->fd_in_tag = 0; ++ } ++} ++ + #ifndef _WIN32 + static GIOChannel *io_channel_from_fd(int fd) + { +@@ -831,10 +839,7 @@ static gboolean fd_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + status = g_io_channel_read_chars(chan, (gchar *)buf, + len, &bytes_read, NULL); + if (status == G_IO_STATUS_EOF) { +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); + return FALSE; + } +@@ -864,11 +869,7 @@ static void fd_chr_update_read_handler(CharDriverState *chr) + { + FDCharDriver *s = chr->opaque; + +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } +- ++ remove_fd_in_watch(chr); + if (s->fd_in) { + chr->fd_in_tag = io_add_watch_poll(s->fd_in, fd_chr_read_poll, + fd_chr_read, chr); +@@ -879,11 +880,7 @@ static void fd_chr_close(struct CharDriverState *chr) + { + FDCharDriver *s = chr->opaque; + +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } +- ++ remove_fd_in_watch(chr); + if (s->fd_in) { + g_io_channel_unref(s->fd_in); + } +@@ -1130,10 +1127,7 @@ static void pty_chr_state(CharDriverState *chr, int connected) + PtyCharDriver *s = chr->opaque; + + if (!connected) { +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + s->connected = 0; + /* (re-)connect poll interval for idle guests: once per second. + * We check more frequently in case the guests sends data to +@@ -1159,10 +1153,7 @@ static void pty_chr_close(struct CharDriverState *chr) + PtyCharDriver *s = chr->opaque; + int fd; + +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + fd = g_io_channel_unix_get_fd(s->fd); + g_io_channel_unref(s->fd); + close(fd); +@@ -2224,10 +2215,7 @@ static gboolean udp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + s->bufcnt = bytes_read; + s->bufptr = s->bufcnt; + if (status != G_IO_STATUS_NORMAL) { +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + return FALSE; + } + +@@ -2245,11 +2233,7 @@ static void udp_chr_update_read_handler(CharDriverState *chr) + { + NetCharDriver *s = chr->opaque; + +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } +- ++ remove_fd_in_watch(chr); + if (s->chan) { + chr->fd_in_tag = io_add_watch_poll(s->chan, udp_chr_read_poll, + udp_chr_read, chr); +@@ -2259,10 +2243,8 @@ static void udp_chr_update_read_handler(CharDriverState *chr) + static void udp_chr_close(CharDriverState *chr) + { + NetCharDriver *s = chr->opaque; +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ ++ remove_fd_in_watch(chr); + if (s->chan) { + g_io_channel_unref(s->chan); + closesocket(s->fd); +@@ -2495,10 +2477,7 @@ static gboolean tcp_chr_read(GIOChannel *chan, GIOCondition cond, void *opaque) + if (s->listen_chan) { + s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); + } +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + g_io_channel_unref(s->chan); + s->chan = NULL; + closesocket(s->fd); +@@ -2612,10 +2591,7 @@ static void tcp_chr_close(CharDriverState *chr) + { + TCPCharDriver *s = chr->opaque; + if (s->fd >= 0) { +- if (chr->fd_in_tag) { +- io_remove_watch_poll(chr->fd_in_tag); +- chr->fd_in_tag = 0; +- } ++ remove_fd_in_watch(chr); + if (s->chan) { + g_io_channel_unref(s->chan); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-chardev-fix-pty_chr_timer.patch b/SOURCES/kvm-chardev-fix-pty_chr_timer.patch new file mode 100644 index 0000000..6a9a24a --- /dev/null +++ b/SOURCES/kvm-chardev-fix-pty_chr_timer.patch @@ -0,0 +1,67 @@ +From 65b9fb19d5853b28b6748963d9e0053429655921 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 18 Sep 2013 09:53:54 +0200 +Subject: [PATCH 01/18] chardev: fix pty_chr_timer + +RH-Author: Gerd Hoffmann +Message-id: <1379498034-29529-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54429 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] chardev: fix pty_chr_timer +Bugzilla: 994414 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +pty_chr_timer first calls pty_chr_update_read_handler(), then clears +timer_tag (because it is a one-shot timer). This is the wrong order +though. pty_chr_update_read_handler might re-arm time timer, and the +new timer_tag gets overwitten in that case. + +This leads to crashes when unplugging a pty chardev: pty_chr_close +thinks no timer is running -> timer isn't canceled -> pty_chr_timer gets +called with stale CharDevState -> BOOM. + +This patch fixes the ordering. +Kill the pointless goto while being at it. + +https://bugzilla.redhat.com/show_bug.cgi?id=994414 + +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit b0d768c35e08d2057b63e8e77e7a513c447199fa) +--- + qemu-char.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 12 ++++-------- + 1 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 2fb876c..660d758 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -1029,15 +1029,11 @@ static gboolean pty_chr_timer(gpointer opaque) + struct CharDriverState *chr = opaque; + PtyCharDriver *s = chr->opaque; + +- if (s->connected) { +- goto out; +- } +- +- /* Next poll ... */ +- pty_chr_update_read_handler(chr); +- +-out: + s->timer_tag = 0; ++ if (!s->connected) { ++ /* Next poll ... */ ++ pty_chr_update_read_handler(chr); ++ } + return FALSE; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-chardev-handle-qmp_chardev_add-KIND_MUX-failure.patch b/SOURCES/kvm-chardev-handle-qmp_chardev_add-KIND_MUX-failure.patch new file mode 100644 index 0000000..7c92ec2 --- /dev/null +++ b/SOURCES/kvm-chardev-handle-qmp_chardev_add-KIND_MUX-failure.patch @@ -0,0 +1,47 @@ +From a498fc16bc9b1bfa983a95ca97dae183d8d4627e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:23 +0200 +Subject: [PATCH 16/18] chardev: handle qmp_chardev_add(KIND_MUX) failure + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-16-git-send-email-kraxel@redhat.com> +Patchwork-id: 54860 +O-Subject: [RHEL-7 qemu-kvm PATCH 15/15] chardev: handle qmp_chardev_add(KIND_MUX) failure +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Cc: Markus Armbruster +Signed-off-by: Gerd Hoffmann +(cherry picked from commit ee6ee83de29923483b4905b35f18abf5333f6ea9) +--- + qemu-char.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index bacc7b7..983f686 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3255,7 +3255,12 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, + backend->kind = CHARDEV_BACKEND_KIND_MUX; + backend->mux->chardev = g_strdup(bid); + ret = qmp_chardev_add(id, backend, errp); +- assert(!error_is_set(errp)); ++ if (error_is_set(errp)) { ++ chr = qemu_chr_find(bid); ++ qemu_chr_delete(chr); ++ chr = NULL; ++ goto qapi_out; ++ } + } + + chr = qemu_chr_find(id); +-- +1.7.1 + diff --git a/SOURCES/kvm-configure-don-t-save-any-fixed-local_statedir-for-wi.patch b/SOURCES/kvm-configure-don-t-save-any-fixed-local_statedir-for-wi.patch new file mode 100644 index 0000000..8edba15 --- /dev/null +++ b/SOURCES/kvm-configure-don-t-save-any-fixed-local_statedir-for-wi.patch @@ -0,0 +1,82 @@ +From a7b1e640330bf53d45d9d68af84df13917907c35 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:24 +0200 +Subject: [PATCH 03/28] configure: don't save any fixed local_statedir for win32 + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-4-git-send-email-lersek@redhat.com> +Patchwork-id: 52865 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/6] configure: don't save any fixed local_statedir for win32 +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +... because now we can get the dynamic value with +qemu_get_local_state_pathname(). + +The only user of the fixed value was the guest agent, which we've moved to +qemu_get_local_state_pathname() in the previous patch. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael Roth +(cherry picked from commit 5a699bbbf300902141d2458682d05cd310d7a07f) +--- + configure | 12 ++++++++---- + 1 files changed, 8 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + configure | 12 ++++++++---- + 1 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/configure b/configure +index a71e8a1..02e483d 100755 +--- a/configure ++++ b/configure +@@ -588,7 +588,7 @@ EOF + qemu_docdir="\${prefix}" + bindir="\${prefix}" + sysconfdir="\${prefix}" +- local_statedir="\${prefix}" ++ local_statedir= + confsuffix="" + libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga" + fi +@@ -1085,7 +1085,7 @@ echo " --docdir=PATH install documentation in PATH$confsuffix" + echo " --bindir=PATH install binaries in PATH" + echo " --libdir=PATH install libraries in PATH" + echo " --sysconfdir=PATH install config in PATH$confsuffix" +-echo " --localstatedir=PATH install local state in PATH" ++echo " --localstatedir=PATH install local state in PATH (set at runtime on win32)" + echo " --with-confsuffix=SUFFIX suffix for QEMU data inside datadir and sysconfdir [$confsuffix]" + echo " --enable-debug-tcg enable TCG debugging" + echo " --disable-debug-tcg disable TCG debugging (default)" +@@ -3495,10 +3495,12 @@ echo "library directory `eval echo $libdir`" + echo "libexec directory `eval echo $libexecdir`" + echo "include directory `eval echo $includedir`" + echo "config directory `eval echo $sysconfdir`" +-echo "local state directory `eval echo $local_statedir`" + if test "$mingw32" = "no" ; then ++echo "local state directory `eval echo $local_statedir`" + echo "Manual directory `eval echo $mandir`" + echo "ELF interp prefix $interp_prefix" ++else ++echo "local state directory queried at runtime" + fi + echo "Source path $source_path" + echo "C compiler $cc" +@@ -3620,7 +3622,9 @@ echo "sysconfdir=$sysconfdir" >> $config_host_mak + echo "qemu_confdir=$qemu_confdir" >> $config_host_mak + echo "qemu_datadir=$qemu_datadir" >> $config_host_mak + echo "qemu_docdir=$qemu_docdir" >> $config_host_mak +-echo "qemu_localstatedir=$local_statedir" >> $config_host_mak ++if test "$mingw32" = "no" ; then ++ echo "qemu_localstatedir=$local_statedir" >> $config_host_mak ++fi + echo "qemu_helperdir=$libexecdir" >> $config_host_mak + echo "extra_cflags=$EXTRA_CFLAGS" >> $config_host_mak + echo "extra_ldflags=$EXTRA_LDFLAGS" >> $config_host_mak +-- +1.7.1 + diff --git a/SOURCES/kvm-cow-do-not-call-bdrv_co_is_allocated.patch b/SOURCES/kvm-cow-do-not-call-bdrv_co_is_allocated.patch new file mode 100644 index 0000000..8b60307 --- /dev/null +++ b/SOURCES/kvm-cow-do-not-call-bdrv_co_is_allocated.patch @@ -0,0 +1,46 @@ +From 48a9eea657b6533556026d5eda813736ab36844b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:28 +0200 +Subject: [PATCH 03/81] cow: do not call bdrv_co_is_allocated + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-4-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54987 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 03/26] cow: do not call bdrv_co_is_allocated +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +As we change bdrv_is_allocated to gather more information from bs and +bs->file, it will become a bit slower. It is still appropriate for online +jobs, but not for reads/writes. Call the internal function instead. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit e641c1e81e54fc14908ff6785ef7d51e42c2e1bb) +--- + block/cow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/cow.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block/cow.c b/block/cow.c +index 2f72334..21bceaa 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -212,7 +212,7 @@ static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num, + int ret, n; + + while (nb_sectors > 0) { +- if (bdrv_co_is_allocated(bs, sector_num, nb_sectors, &n)) { ++ if (cow_co_is_allocated(bs, sector_num, nb_sectors, &n)) { + ret = bdrv_pread(bs->file, + s->cow_sectors_offset + sector_num * 512, + buf, n * 512); +-- +1.7.1 + diff --git a/SOURCES/kvm-cow-make-reads-go-at-a-decent-speed.patch b/SOURCES/kvm-cow-make-reads-go-at-a-decent-speed.patch new file mode 100644 index 0000000..3ce3693 --- /dev/null +++ b/SOURCES/kvm-cow-make-reads-go-at-a-decent-speed.patch @@ -0,0 +1,113 @@ +From 2a46f74bc62cd8affeb7516d1adf5dd855f3ed5a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:26 +0200 +Subject: [PATCH 01/81] cow: make reads go at a decent speed + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-2-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54983 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 01/26] cow: make reads go at a decent speed +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Do not do two reads for each sector; load each sector of the bitmap +and use bitmap operations to process it. + +Writes are still dog slow! + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 276cbc7f2fc1bd3810887995dbc9cbb739c975bf) +--- + block/cow.c | 54 ++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 22 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/cow.c | 54 ++++++++++++++++++++++++++++++++---------------------- + 1 files changed, 32 insertions(+), 22 deletions(-) + +diff --git a/block/cow.c b/block/cow.c +index 9f94599..c12088b 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -126,18 +126,31 @@ static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum) + return 0; + } + +-static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum) ++#define BITS_PER_BITMAP_SECTOR (512 * 8) ++ ++/* Cannot use bitmap.c on big-endian machines. */ ++static int cow_test_bit(int64_t bitnum, const uint8_t *bitmap) + { +- uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8; +- uint8_t bitmap; +- int ret; ++ return (bitmap[bitnum / 8] & (1 << (bitnum & 7))) != 0; ++} + +- ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)); +- if (ret < 0) { +- return ret; ++static int cow_find_streak(const uint8_t *bitmap, int value, int start, int nb_sectors) ++{ ++ int streak_value = value ? 0xFF : 0; ++ int last = MIN(start + nb_sectors, BITS_PER_BITMAP_SECTOR); ++ int bitnum = start; ++ while (bitnum < last) { ++ if ((bitnum & 7) == 0 && bitmap[bitnum / 8] == streak_value) { ++ bitnum += 8; ++ continue; ++ } ++ if (cow_test_bit(bitnum, bitmap) == value) { ++ bitnum++; ++ continue; ++ } ++ break; + } +- +- return !!(bitmap & (1 << (bitnum % 8))); ++ return MIN(bitnum, last) - start; + } + + /* Return true if first block has been changed (ie. current version is +@@ -146,23 +159,20 @@ static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum) + static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs, + int64_t sector_num, int nb_sectors, int *num_same) + { ++ int64_t bitnum = sector_num + sizeof(struct cow_header_v2) * 8; ++ uint64_t offset = (bitnum / 8) & -BDRV_SECTOR_SIZE; ++ uint8_t bitmap[BDRV_SECTOR_SIZE]; ++ int ret; + int changed; + +- if (nb_sectors == 0) { +- *num_same = nb_sectors; +- return 0; +- } +- +- changed = is_bit_set(bs, sector_num); +- if (changed < 0) { +- return 0; /* XXX: how to return I/O errors? */ +- } +- +- for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) { +- if (is_bit_set(bs, sector_num + *num_same) != changed) +- break; ++ ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)); ++ if (ret < 0) { ++ return ret; + } + ++ bitnum &= BITS_PER_BITMAP_SECTOR - 1; ++ changed = cow_test_bit(bitnum, bitmap); ++ *num_same = cow_find_streak(bitmap, changed, bitnum, nb_sectors); + return changed; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-cow-make-writes-go-at-a-less-indecent-speed.patch b/SOURCES/kvm-cow-make-writes-go-at-a-less-indecent-speed.patch new file mode 100644 index 0000000..9d16530 --- /dev/null +++ b/SOURCES/kvm-cow-make-writes-go-at-a-less-indecent-speed.patch @@ -0,0 +1,79 @@ +From a1a7f1301c20582d3326e33acd94a4c198c60bcd Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:27 +0200 +Subject: [PATCH 02/81] cow: make writes go at a less indecent speed + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-3-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54985 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 02/26] cow: make writes go at a less indecent speed +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Only sync once per write, rather than once per sector. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 26ae980492920e417bc91761cc85950f18e41f85) +--- + block/cow.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/cow.c | 19 ++++++++++++++++--- + 1 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/block/cow.c b/block/cow.c +index c12088b..2f72334 100644 +--- a/block/cow.c ++++ b/block/cow.c +@@ -106,7 +106,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags) + * XXX(hch): right now these functions are extremely inefficient. + * We should just read the whole bitmap we'll need in one go instead. + */ +-static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum) ++static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum, bool *first) + { + uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8; + uint8_t bitmap; +@@ -117,9 +117,21 @@ static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum) + return ret; + } + ++ if (bitmap & (1 << (bitnum % 8))) { ++ return 0; ++ } ++ ++ if (*first) { ++ ret = bdrv_flush(bs->file); ++ if (ret < 0) { ++ return ret; ++ } ++ *first = false; ++ } ++ + bitmap |= (1 << (bitnum % 8)); + +- ret = bdrv_pwrite_sync(bs->file, offset, &bitmap, sizeof(bitmap)); ++ ret = bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap)); + if (ret < 0) { + return ret; + } +@@ -181,9 +193,10 @@ static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num, + { + int error = 0; + int i; ++ bool first = true; + + for (i = 0; i < nb_sectors; i++) { +- error = cow_set_bit(bs, sector_num + i); ++ error = cow_set_bit(bs, sector_num + i, &first); + if (error) { + break; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-cpu-Document-why-cannot_instantiate_with_device_add_.patch b/SOURCES/kvm-cpu-Document-why-cannot_instantiate_with_device_add_.patch new file mode 100644 index 0000000..d5be296 --- /dev/null +++ b/SOURCES/kvm-cpu-Document-why-cannot_instantiate_with_device_add_.patch @@ -0,0 +1,50 @@ +From d7eb9186c64094d6413bf98220e04b5350d2292d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:14 +0100 +Subject: [PATCH 38/81] cpu: Document why cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-10-git-send-email-kwolf@redhat.com> +Patchwork-id: 55535 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 09/17] cpu: Document why cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Peter Maydell +(cherry picked from pending upstream submission) +Signed-off-by: Kevin Wolf +--- + qom/cpu.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qom/cpu.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/qom/cpu.c b/qom/cpu.c +index f97e1b8..859dae5 100644 +--- a/qom/cpu.c ++++ b/qom/cpu.c +@@ -210,7 +210,11 @@ static void cpu_class_init(ObjectClass *klass, void *data) + k->write_elf64_qemunote = cpu_common_write_elf64_qemunote; + k->write_elf64_note = cpu_common_write_elf64_note; + dc->realize = cpu_common_realizefn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ ++ /* ++ * Reason: CPUs still need special care by board code: wiring up ++ * IRQs, adding reset handlers, halting non-first CPUS, ... ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo cpu_type_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-cpu-Turn-cpu_get_memory_mapping-into-a-CPUState-hook.patch b/SOURCES/kvm-cpu-Turn-cpu_get_memory_mapping-into-a-CPUState-hook.patch new file mode 100644 index 0000000..668c94e --- /dev/null +++ b/SOURCES/kvm-cpu-Turn-cpu_get_memory_mapping-into-a-CPUState-hook.patch @@ -0,0 +1,208 @@ +From 4a8aa152fc7244b36cae10a64759ec1c50bc9c87 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:34 +0200 +Subject: cpu: Turn cpu_get_memory_mapping() into a CPUState hook + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-5-git-send-email-lersek@redhat.com> +Patchwork-id: 53163 +O-Subject: [RHEL-7 qemu-kvm PATCH 04/10] cpu: Turn cpu_get_memory_mapping() into a CPUState hook +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +From: Andreas Färber + +Change error reporting from return value to Error argument. + +Reviewed-by: Jens Freimann +Reviewed-by: Luiz Capitulino +[AF: Fixed cpu_get_memory_mapping() documentation] +Signed-off-by: Andreas Färber +(cherry picked from commit a23bbfda75118eb738acce84afd64965934828f0) +Signed-off-by: Laszlo Ersek + +diff --git a/include/qom/cpu.h b/include/qom/cpu.h +index 490f5f1..b555c22 100644 +--- a/include/qom/cpu.h ++++ b/include/qom/cpu.h +@@ -23,6 +23,7 @@ + #include + #include "hw/qdev-core.h" + #include "qemu/thread.h" ++#include "qemu/typedefs.h" + + typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque); + +@@ -49,6 +50,7 @@ typedef struct CPUState CPUState; + * @do_interrupt: Callback for interrupt handling. + * @get_arch_id: Callback for getting architecture-dependent CPU ID. + * @get_paging_enabled: Callback for inquiring whether paging is enabled. ++ * @get_memory_mapping: Callback for obtaining the memory mappings. + * @vmsd: State description for migration. + * + * Represents a CPU family or model. +@@ -64,6 +66,8 @@ typedef struct CPUClass { + void (*do_interrupt)(CPUState *cpu); + int64_t (*get_arch_id)(CPUState *cpu); + bool (*get_paging_enabled)(const CPUState *cpu); ++ void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list, ++ Error **errp); + + const struct VMStateDescription *vmsd; + int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu, +@@ -148,6 +152,15 @@ struct CPUState { + bool cpu_paging_enabled(const CPUState *cpu); + + /** ++ * cpu_get_memory_mapping: ++ * @cpu: The CPU whose memory mappings are to be obtained. ++ * @list: Where to write the memory mappings to. ++ * @errp: Pointer for reporting an #Error. ++ */ ++void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, ++ Error **errp); ++ ++/** + * cpu_write_elf64_note: + * @f: pointer to a function that writes memory to a file + * @cpu: The CPU whose memory is to be dumped +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index 1f71c32..c47e6ee 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -31,8 +31,6 @@ struct MemoryMappingList { + QTAILQ_HEAD(, MemoryMapping) head; + }; + +-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env); +- + /* + * add or merge the memory region [phys_addr, phys_addr + length) into the + * memory mapping's list. The region's virtual address starts with virt_addr, +diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c +index 6c0dfeb..989dc00 100644 +--- a/memory_mapping-stub.c ++++ b/memory_mapping-stub.c +@@ -19,9 +19,3 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list) + { + return -2; + } +- +-int cpu_get_memory_mapping(MemoryMappingList *list, +- CPUArchState *env) +-{ +- return -1; +-} +diff --git a/memory_mapping.c b/memory_mapping.c +index 0790aac..9bd24ce 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -183,13 +183,14 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list) + CPUArchState *env, *first_paging_enabled_cpu; + RAMBlock *block; + ram_addr_t offset, length; +- int ret; + + first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu); + if (first_paging_enabled_cpu) { + for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) { +- ret = cpu_get_memory_mapping(list, env); +- if (ret < 0) { ++ Error *err = NULL; ++ cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err); ++ if (err) { ++ error_free(err); + return -1; + } + } +diff --git a/qom/cpu.c b/qom/cpu.c +index 9f6da0f..b25fbc9 100644 +--- a/qom/cpu.c ++++ b/qom/cpu.c +@@ -62,6 +62,21 @@ static bool cpu_common_get_paging_enabled(const CPUState *cpu) + return true; + } + ++void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, ++ Error **errp) ++{ ++ CPUClass *cc = CPU_GET_CLASS(cpu); ++ ++ return cc->get_memory_mapping(cpu, list, errp); ++} ++ ++static void cpu_common_get_memory_mapping(CPUState *cpu, ++ MemoryMappingList *list, ++ Error **errp) ++{ ++ error_setg(errp, "Obtaining memory mappings is unsupported on this CPU."); ++} ++ + /* CPU hot-plug notifiers */ + static NotifierList cpu_added_notifiers = + NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers); +@@ -189,6 +204,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) + k->reset = cpu_common_reset; + k->get_arch_id = cpu_common_get_arch_id; + k->get_paging_enabled = cpu_common_get_paging_enabled; ++ k->get_memory_mapping = cpu_common_get_memory_mapping; + k->write_elf32_qemunote = cpu_common_write_elf32_qemunote; + k->write_elf32_note = cpu_common_write_elf32_note; + k->write_elf64_qemunote = cpu_common_write_elf64_qemunote; +diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c +index 39def3d..ca47970 100644 +--- a/target-i386/arch_memory_mapping.c ++++ b/target-i386/arch_memory_mapping.c +@@ -239,11 +239,15 @@ static void walk_pml4e(MemoryMappingList *list, + } + #endif + +-int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) ++void x86_cpu_get_memory_mapping(CPUState *cs, MemoryMappingList *list, ++ Error **errp) + { +- if (!cpu_paging_enabled(ENV_GET_CPU(env))) { ++ X86CPU *cpu = X86_CPU(cs); ++ CPUX86State *env = &cpu->env; ++ ++ if (!cpu_paging_enabled(cs)) { + /* paging is disabled */ +- return 0; ++ return; + } + + if (env->cr[4] & CR4_PAE_MASK) { +@@ -269,7 +273,5 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) + pse = !!(env->cr[4] & CR4_PSE_MASK); + walk_pde2(list, pde_addr, env->a20_mask, pse); + } +- +- return 0; + } + +diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h +index 5231005..12c7bea 100644 +--- a/target-i386/cpu-qom.h ++++ b/target-i386/cpu-qom.h +@@ -105,4 +105,7 @@ int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu, + int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, + void *opaque); + ++void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, ++ Error **errp); ++ + #endif +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index dfa2a86..e915157 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -2540,6 +2540,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + cc->get_arch_id = x86_cpu_get_arch_id; + cc->get_paging_enabled = x86_cpu_get_paging_enabled; + #ifndef CONFIG_USER_ONLY ++ cc->get_memory_mapping = x86_cpu_get_memory_mapping; + cc->write_elf64_note = x86_cpu_write_elf64_note; + cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote; + cc->write_elf32_note = x86_cpu_write_elf32_note; diff --git a/SOURCES/kvm-cpu-Turn-cpu_paging_enabled-into-a-CPUState-hook.patch b/SOURCES/kvm-cpu-Turn-cpu_paging_enabled-into-a-CPUState-hook.patch new file mode 100644 index 0000000..6154b89 --- /dev/null +++ b/SOURCES/kvm-cpu-Turn-cpu_paging_enabled-into-a-CPUState-hook.patch @@ -0,0 +1,195 @@ +From 0fb4264531471230dfe37f1c04d38cd46e38027a Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:32 +0200 +Subject: cpu: Turn cpu_paging_enabled() into a CPUState hook + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-3-git-send-email-lersek@redhat.com> +Patchwork-id: 53161 +O-Subject: [RHEL-7 qemu-kvm PATCH 02/10] cpu: Turn cpu_paging_enabled() into a CPUState hook +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +Relocate assignment of x86 get_arch_id to have all hooks in one place. + +Reviewed-by: Jens Freimann +Reviewed-by: Luiz Capitulino +Signed-off-by: Andreas Färber +(cherry picked from commit 444d55907871f88276a654fc7fdc8c7db95f4b59) + +Conflicts (due to RHEL-7 commit c93d9248, "target-i386: Disable PMU CPUID +leaf by default"): + + target-i386/cpu.c +Signed-off-by: Laszlo Ersek + +diff --git a/include/qom/cpu.h b/include/qom/cpu.h +index 46465e9..490f5f1 100644 +--- a/include/qom/cpu.h ++++ b/include/qom/cpu.h +@@ -48,6 +48,7 @@ typedef struct CPUState CPUState; + * @reset: Callback to reset the #CPUState to its initial state. + * @do_interrupt: Callback for interrupt handling. + * @get_arch_id: Callback for getting architecture-dependent CPU ID. ++ * @get_paging_enabled: Callback for inquiring whether paging is enabled. + * @vmsd: State description for migration. + * + * Represents a CPU family or model. +@@ -62,6 +63,7 @@ typedef struct CPUClass { + void (*reset)(CPUState *cpu); + void (*do_interrupt)(CPUState *cpu); + int64_t (*get_arch_id)(CPUState *cpu); ++ bool (*get_paging_enabled)(const CPUState *cpu); + + const struct VMStateDescription *vmsd; + int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu, +@@ -138,6 +140,14 @@ struct CPUState { + }; + + /** ++ * cpu_paging_enabled: ++ * @cpu: The CPU whose state is to be inspected. ++ * ++ * Returns: %true if paging is enabled, %false otherwise. ++ */ ++bool cpu_paging_enabled(const CPUState *cpu); ++ ++/** + * cpu_write_elf64_note: + * @f: pointer to a function that writes memory to a file + * @cpu: The CPU whose memory is to be dumped +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index 1256125..6f01524 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -31,7 +31,6 @@ typedef struct MemoryMappingList { + } MemoryMappingList; + + int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env); +-bool cpu_paging_enabled(CPUArchState *env); + + /* + * add or merge the memory region [phys_addr, phys_addr + length) into the +diff --git a/memory_mapping-stub.c b/memory_mapping-stub.c +index 24d5d67..6c0dfeb 100644 +--- a/memory_mapping-stub.c ++++ b/memory_mapping-stub.c +@@ -25,9 +25,3 @@ int cpu_get_memory_mapping(MemoryMappingList *list, + { + return -1; + } +- +-bool cpu_paging_enabled(CPUArchState *env) +-{ +- return true; +-} +- +diff --git a/memory_mapping.c b/memory_mapping.c +index ff45b3a..0790aac 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -170,7 +170,7 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) + CPUArchState *env; + + for (env = start_cpu; env != NULL; env = env->next_cpu) { +- if (cpu_paging_enabled(env)) { ++ if (cpu_paging_enabled(ENV_GET_CPU(env))) { + return env; + } + } +diff --git a/qom/cpu.c b/qom/cpu.c +index 04aefbb..9f6da0f 100644 +--- a/qom/cpu.c ++++ b/qom/cpu.c +@@ -50,6 +50,18 @@ bool cpu_exists(int64_t id) + return data.found; + } + ++bool cpu_paging_enabled(const CPUState *cpu) ++{ ++ CPUClass *cc = CPU_GET_CLASS(cpu); ++ ++ return cc->get_paging_enabled(cpu); ++} ++ ++static bool cpu_common_get_paging_enabled(const CPUState *cpu) ++{ ++ return true; ++} ++ + /* CPU hot-plug notifiers */ + static NotifierList cpu_added_notifiers = + NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers); +@@ -176,6 +188,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) + k->class_by_name = cpu_common_class_by_name; + k->reset = cpu_common_reset; + k->get_arch_id = cpu_common_get_arch_id; ++ k->get_paging_enabled = cpu_common_get_paging_enabled; + k->write_elf32_qemunote = cpu_common_write_elf32_qemunote; + k->write_elf32_note = cpu_common_write_elf32_note; + k->write_elf64_qemunote = cpu_common_write_elf64_qemunote; +diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c +index 24884bd..39def3d 100644 +--- a/target-i386/arch_memory_mapping.c ++++ b/target-i386/arch_memory_mapping.c +@@ -241,7 +241,7 @@ static void walk_pml4e(MemoryMappingList *list, + + int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) + { +- if (!cpu_paging_enabled(env)) { ++ if (!cpu_paging_enabled(ENV_GET_CPU(env))) { + /* paging is disabled */ + return 0; + } +@@ -273,7 +273,3 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env) + return 0; + } + +-bool cpu_paging_enabled(CPUArchState *env) +-{ +- return env->cr[0] & CR0_PG_MASK; +-} +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 2bcc21e..dfa2a86 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -2509,11 +2509,19 @@ static int64_t x86_cpu_get_arch_id(CPUState *cs) + return env->cpuid_apic_id; + } + ++ + static Property x86_cpu_properties[] = { + DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), + DEFINE_PROP_END_OF_LIST() + }; + ++static bool x86_cpu_get_paging_enabled(const CPUState *cs) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ ++ return cpu->env.cr[0] & CR0_PG_MASK; ++} ++ + static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + { + X86CPUClass *xcc = X86_CPU_CLASS(oc); +@@ -2529,6 +2537,8 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + cc->reset = x86_cpu_reset; + + cc->do_interrupt = x86_cpu_do_interrupt; ++ cc->get_arch_id = x86_cpu_get_arch_id; ++ cc->get_paging_enabled = x86_cpu_get_paging_enabled; + #ifndef CONFIG_USER_ONLY + cc->write_elf64_note = x86_cpu_write_elf64_note; + cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote; +@@ -2536,8 +2546,6 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote; + #endif + cpu_class_set_vmsd(cc, &vmstate_x86_cpu); +- +- cc->get_arch_id = x86_cpu_get_arch_id; + } + + static const TypeInfo x86_cpu_type_info = { diff --git a/SOURCES/kvm-cpus-use-error_setg_file_open.patch b/SOURCES/kvm-cpus-use-error_setg_file_open.patch new file mode 100644 index 0000000..a332db6 --- /dev/null +++ b/SOURCES/kvm-cpus-use-error_setg_file_open.patch @@ -0,0 +1,54 @@ +From 36268b43efcc3d639e973a4a47cb32d38e92bc93 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:27 +0100 +Subject: [PATCH 08/29] cpus: use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-5-git-send-email-lersek@redhat.com> +Patchwork-id: 55194 +O-Subject: [RHEL-7 qemu-kvm PATCH 4/8] cpus: use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit 618da851ec8059460be8e0670bc835d3c2003708) +Signed-off-by: Laszlo Ersek +--- + cpus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + cpus.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/cpus.c b/cpus.c +index 3b7b380..caccf5a 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -1316,7 +1316,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char *filename, + + f = fopen(filename, "wb"); + if (!f) { +- error_set(errp, QERR_OPEN_FILE_FAILED, filename); ++ error_setg_file_open(errp, errno, filename); + return; + } + +@@ -1346,7 +1346,7 @@ void qmp_pmemsave(int64_t addr, int64_t size, const char *filename, + + f = fopen(filename, "wb"); + if (!f) { +- error_set(errp, QERR_OPEN_FILE_FAILED, filename); ++ error_setg_file_open(errp, errno, filename); + return; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-dataplane-enable-virtio-blk-x-data-plane-on-live-migration.patch b/SOURCES/kvm-dataplane-enable-virtio-blk-x-data-plane-on-live-migration.patch new file mode 100644 index 0000000..fd4ab49 --- /dev/null +++ b/SOURCES/kvm-dataplane-enable-virtio-blk-x-data-plane-on-live-migration.patch @@ -0,0 +1,145 @@ +From 714d313805542063ea68e26a0d47b5059ee9952e Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 13 Aug 2013 09:06:36 +0200 +Subject: dataplane: enable virtio-blk x-data-plane=on live migration + +RH-Author: Stefan Hajnoczi +Message-id: <1376384797-4701-6-git-send-email-stefanha@redhat.com> +Patchwork-id: 53210 +O-Subject: [PATCH v2 5/6] dataplane: enable virtio-blk x-data-plane=on live migration +Bugzilla: 995030 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Kevin Wolf +RH-Acked-by: Michael S. Tsirkin + +Although the dataplane thread does not cooperate with dirty memory +logging yet it's fairly easy to temporarily disable dataplane during +live migration. This way virtio-blk can live migrate when +x-data-plane=on. + +The dataplane thread will restart after migration is cancelled or if the +guest resuming virtio-blk operation after migration completes. + +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 84db52d059f3296abf7783968645c4a96d21b099) + +Signed-off-by: Stefan Hajnoczi + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 2faed43..63c3ffa 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -18,7 +18,6 @@ + #include "qemu/error-report.h" + #include "hw/virtio/dataplane/vring.h" + #include "ioq.h" +-#include "migration/migration.h" + #include "block/block.h" + #include "hw/virtio/virtio-blk.h" + #include "virtio-blk.h" +@@ -69,8 +68,6 @@ struct VirtIOBlockDataPlane { + queue */ + + unsigned int num_reqs; +- +- Error *migration_blocker; + }; + + /* Raise an interrupt to signal guest, if necessary */ +@@ -433,10 +430,6 @@ bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk, + /* Prevent block operations that conflict with data plane thread */ + bdrv_set_in_use(blk->conf.bs, 1); + +- error_setg(&s->migration_blocker, +- "x-data-plane does not support migration"); +- migrate_add_blocker(s->migration_blocker); +- + *dataplane = s; + return true; + } +@@ -448,8 +441,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) + } + + virtio_blk_data_plane_stop(s); +- migrate_del_blocker(s->migration_blocker); +- error_free(s->migration_blocker); + bdrv_set_in_use(s->blk->conf.bs, 0); + g_free(s); + } +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index cf12469..cca0c77 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -19,6 +19,7 @@ + #include "hw/virtio/virtio-blk.h" + #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + # include "dataplane/virtio-blk.h" ++# include "migration/migration.h" + #endif + #include "block/scsi.h" + #ifdef __linux__ +@@ -628,6 +629,34 @@ void virtio_blk_set_conf(DeviceState *dev, VirtIOBlkConf *blk) + memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf)); + } + ++#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE ++/* Disable dataplane thread during live migration since it does not ++ * update the dirty memory bitmap yet. ++ */ ++static void virtio_blk_migration_state_changed(Notifier *notifier, void *data) ++{ ++ VirtIOBlock *s = container_of(notifier, VirtIOBlock, ++ migration_state_notifier); ++ MigrationState *mig = data; ++ ++ if (migration_is_active(mig)) { ++ if (!s->dataplane) { ++ return; ++ } ++ virtio_blk_data_plane_destroy(s->dataplane); ++ s->dataplane = NULL; ++ } else if (migration_has_finished(mig) || ++ migration_has_failed(mig)) { ++ if (s->dataplane) { ++ return; ++ } ++ bdrv_drain_all(); /* complete in-flight non-dataplane requests */ ++ virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->blk, ++ &s->dataplane); ++ } ++} ++#endif /* CONFIG_VIRTIO_BLK_DATA_PLANE */ ++ + static int virtio_blk_device_init(VirtIODevice *vdev) + { + DeviceState *qdev = DEVICE(vdev); +@@ -664,6 +693,8 @@ static int virtio_blk_device_init(VirtIODevice *vdev) + virtio_cleanup(vdev); + return -1; + } ++ s->migration_state_notifier.notify = virtio_blk_migration_state_changed; ++ add_migration_state_change_notifier(&s->migration_state_notifier); + #endif + + s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); +@@ -683,6 +714,7 @@ static int virtio_blk_device_exit(DeviceState *dev) + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOBlock *s = VIRTIO_BLK(dev); + #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE ++ remove_migration_state_change_notifier(&s->migration_state_notifier); + virtio_blk_data_plane_destroy(s->dataplane); + s->dataplane = NULL; + #endif +diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h +index fc71853..b87cf49 100644 +--- a/include/hw/virtio/virtio-blk.h ++++ b/include/hw/virtio/virtio-blk.h +@@ -125,6 +125,7 @@ typedef struct VirtIOBlock { + unsigned short sector_mask; + VMChangeStateEntry *change; + #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE ++ Notifier migration_state_notifier; + struct VirtIOBlockDataPlane *dataplane; + #endif + } VirtIOBlock; diff --git a/SOURCES/kvm-devices-Associate-devices-to-their-logical-category.patch b/SOURCES/kvm-devices-Associate-devices-to-their-logical-category.patch new file mode 100644 index 0000000..ea78e15 --- /dev/null +++ b/SOURCES/kvm-devices-Associate-devices-to-their-logical-category.patch @@ -0,0 +1,1848 @@ +From 2fecbf68b60416c352ded3ea496028b477cce6b4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:09 +0100 +Subject: [PATCH 33/81] devices: Associate devices to their logical category + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-5-git-send-email-kwolf@redhat.com> +Patchwork-id: 55530 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 04/17] devices: Associate devices to their logical category +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Marcel Apfelbaum + +The category will be used to sort the devices displayed in +the command line help. + +Signed-off-by: Marcel Apfelbaum +Message-id: 1375107465-25767-4-git-send-email-marcel.a@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 125ee0ed9cad04307498ac2b7b0d51ad8a807360) + +Conflicts: + hw/audio/adlib.c + hw/audio/cs4231a.c + hw/audio/gus.c + hw/audio/pcspk.c + hw/audio/sb16.c + hw/block/nvme.c + hw/misc/pc-testdev.c + hw/misc/sga.c + hw/pci-bridge/i82801b11.c + hw/usb/hcd-ehci-sysbus.c + hw/usb/hcd-ohci.c + hw/virtio/virtio-mmio.c + +Trivial conflicts in + +* ISA devices because we don't have commit db895a1 "isa: Use realizefn + for ISADevice" + +* i82801b11.c because we backported commit 4965b7f out of order, as + commit ccf2798 + +* hcd-ehci-sysbus because we don't have commit 20c5704 "usb/hcd-ehci: + Add Tegra2 SysBus EHCI device" and commit 4e3d8b4 "usb/hcd-ehci: Add + Faraday FUSBH200 support" + +* hcd-ohci.c because we don't have commit 457215e "ohci: Use QOM + realize for OHCI" + +* nvme.c and virtio-mmio.c because we don't have them +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/9pfs/virtio-9p-device.c | 1 + + hw/audio/ac97.c | 1 + + hw/audio/adlib.c | 1 + + hw/audio/cs4231a.c | 1 + + hw/audio/es1370.c | 1 + + hw/audio/gus.c | 1 + + hw/audio/hda-codec.c | 3 +++ + hw/audio/intel-hda.c | 3 +++ + hw/audio/pcspk.c | 1 + + hw/audio/pl041.c | 1 + + hw/audio/sb16.c | 1 + + hw/block/fdc.c | 3 +++ + hw/block/pc_sysfw.c | 1 + + hw/block/pflash_cfi01.c | 1 + + hw/block/virtio-blk.c | 1 + + hw/char/debugcon.c | 1 + + hw/char/imx_serial.c | 1 + + hw/char/ipack.c | 1 + + hw/char/ipoctal232.c | 1 + + hw/char/parallel.c | 1 + + hw/char/serial-isa.c | 1 + + hw/char/serial-pci.c | 3 +++ + hw/char/tpci200.c | 1 + + hw/char/virtio-serial-bus.c | 2 ++ + hw/cpu/icc_bus.c | 8 ++++++++ + hw/display/cirrus_vga.c | 2 ++ + hw/display/g364fb.c | 1 + + hw/display/pl110.c | 3 +++ + hw/display/qxl.c | 2 ++ + hw/display/vga-isa.c | 1 + + hw/display/vga-pci.c | 1 + + hw/display/vmware_vga.c | 1 + + hw/i2c/bitbang_i2c.c | 1 + + hw/i2c/core.c | 1 + + hw/i386/kvm/pci-assign.c | 1 + + hw/ide/ahci.c | 1 + + hw/ide/ich.c | 1 + + hw/ide/isa.c | 1 + + hw/ide/piix.c | 3 +++ + hw/ide/qdev.c | 1 + + hw/ide/via.c | 1 + + hw/isa/i82378.c | 1 + + hw/isa/lpc_ich9.c | 1 + + hw/isa/vt82c686.c | 3 +++ + hw/misc/applesmc.c | 1 + + hw/misc/debugexit.c | 1 + + hw/misc/ivshmem.c | 1 + + hw/misc/pc-testdev.c | 2 ++ + hw/misc/pci-testdev.c | 1 + + hw/misc/sga.c | 1 + + hw/misc/vfio.c | 1 + + hw/net/e1000.c | 1 + + hw/net/eepro100.c | 1 + + hw/net/lance.c | 1 + + hw/net/mipsnet.c | 1 + + hw/net/ne2000-isa.c | 1 + + hw/net/ne2000.c | 1 + + hw/net/opencores_eth.c | 1 + + hw/net/pcnet-pci.c | 1 + + hw/net/rtl8139.c | 1 + + hw/net/virtio-net.c | 1 + + hw/net/vmxnet3.c | 1 + + hw/pci-bridge/i82801b11.c | 2 ++ + hw/pci-bridge/ioh3420.c | 1 + + hw/pci-bridge/pci_bridge_dev.c | 1 + + hw/pci-bridge/xio3130_downstream.c | 1 + + hw/pci-bridge/xio3130_upstream.c | 1 + + hw/pci-host/apb.c | 2 ++ + hw/pci-host/ppce500.c | 1 + + hw/pci-host/prep.c | 1 + + hw/pci-host/q35.c | 2 ++ + hw/scsi/esp-pci.c | 2 ++ + hw/scsi/esp.c | 1 + + hw/scsi/lsi53c895a.c | 1 + + hw/scsi/megasas.c | 1 + + hw/scsi/scsi-bus.c | 1 + + hw/scsi/vhost-scsi.c | 1 + + hw/scsi/virtio-scsi.c | 3 +++ + hw/scsi/vmw_pvscsi.c | 1 + + hw/usb/ccid-card-emulated.c | 1 + + hw/usb/ccid-card-passthru.c | 1 + + hw/usb/dev-audio.c | 1 + + hw/usb/dev-bluetooth.c | 1 + + hw/usb/dev-hid.c | 3 +++ + hw/usb/dev-hub.c | 1 + + hw/usb/dev-network.c | 1 + + hw/usb/dev-serial.c | 2 ++ + hw/usb/dev-smartcard-reader.c | 1 + + hw/usb/dev-storage.c | 1 + + hw/usb/dev-uas.c | 1 + + hw/usb/dev-wacom.c | 1 + + hw/usb/hcd-ehci-pci.c | 2 ++ + hw/usb/hcd-ehci-sysbus.c | 5 +++++ + hw/usb/hcd-ohci.c | 2 ++ + hw/usb/hcd-uhci.c | 1 + + hw/usb/hcd-xhci.c | 1 + + hw/usb/host-libusb.c | 1 + + hw/usb/redirect.c | 1 + + hw/virtio/virtio-balloon.c | 1 + + hw/virtio/virtio-pci.c | 8 ++++++++ + hw/virtio/virtio-rng.c | 1 + + hw/watchdog/wdt_i6300esb.c | 1 + + hw/watchdog/wdt_ib700.c | 1 + + hw/xen/xen_platform.c | 1 + + hw/xen/xen_pt.c | 1 + + 105 files changed, 152 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/9pfs/virtio-9p-device.c | 1 + + hw/audio/ac97.c | 1 + + hw/audio/adlib.c | 1 + + hw/audio/cs4231a.c | 1 + + hw/audio/es1370.c | 1 + + hw/audio/gus.c | 1 + + hw/audio/hda-codec.c | 3 +++ + hw/audio/intel-hda.c | 3 +++ + hw/audio/pcspk.c | 1 + + hw/audio/pl041.c | 1 + + hw/audio/sb16.c | 1 + + hw/block/fdc.c | 3 +++ + hw/block/pc_sysfw.c | 1 + + hw/block/pflash_cfi01.c | 1 + + hw/block/virtio-blk.c | 1 + + hw/char/debugcon.c | 1 + + hw/char/imx_serial.c | 1 + + hw/char/ipack.c | 1 + + hw/char/ipoctal232.c | 1 + + hw/char/parallel.c | 1 + + hw/char/serial-isa.c | 1 + + hw/char/serial-pci.c | 3 +++ + hw/char/tpci200.c | 1 + + hw/char/virtio-serial-bus.c | 2 ++ + hw/cpu/icc_bus.c | 8 ++++++++ + hw/display/cirrus_vga.c | 2 ++ + hw/display/g364fb.c | 1 + + hw/display/pl110.c | 3 +++ + hw/display/qxl.c | 2 ++ + hw/display/vga-isa.c | 1 + + hw/display/vga-pci.c | 1 + + hw/display/vmware_vga.c | 1 + + hw/i2c/bitbang_i2c.c | 1 + + hw/i2c/core.c | 1 + + hw/i386/kvm/pci-assign.c | 1 + + hw/ide/ahci.c | 1 + + hw/ide/ich.c | 1 + + hw/ide/isa.c | 1 + + hw/ide/piix.c | 3 +++ + hw/ide/qdev.c | 1 + + hw/ide/via.c | 1 + + hw/isa/i82378.c | 1 + + hw/isa/lpc_ich9.c | 1 + + hw/isa/vt82c686.c | 3 +++ + hw/misc/applesmc.c | 1 + + hw/misc/debugexit.c | 1 + + hw/misc/ivshmem.c | 1 + + hw/misc/pc-testdev.c | 2 ++ + hw/misc/pci-testdev.c | 1 + + hw/misc/sga.c | 1 + + hw/misc/vfio.c | 1 + + hw/net/e1000.c | 1 + + hw/net/eepro100.c | 1 + + hw/net/lance.c | 1 + + hw/net/mipsnet.c | 1 + + hw/net/ne2000-isa.c | 1 + + hw/net/ne2000.c | 1 + + hw/net/opencores_eth.c | 1 + + hw/net/pcnet-pci.c | 1 + + hw/net/rtl8139.c | 1 + + hw/net/virtio-net.c | 1 + + hw/net/vmxnet3.c | 1 + + hw/pci-bridge/i82801b11.c | 2 ++ + hw/pci-bridge/ioh3420.c | 1 + + hw/pci-bridge/pci_bridge_dev.c | 1 + + hw/pci-bridge/xio3130_downstream.c | 1 + + hw/pci-bridge/xio3130_upstream.c | 1 + + hw/pci-host/apb.c | 2 ++ + hw/pci-host/ppce500.c | 1 + + hw/pci-host/prep.c | 1 + + hw/pci-host/q35.c | 2 ++ + hw/scsi/esp-pci.c | 2 ++ + hw/scsi/esp.c | 1 + + hw/scsi/lsi53c895a.c | 1 + + hw/scsi/megasas.c | 1 + + hw/scsi/scsi-bus.c | 1 + + hw/scsi/vhost-scsi.c | 1 + + hw/scsi/virtio-scsi.c | 3 +++ + hw/scsi/vmw_pvscsi.c | 1 + + hw/usb/ccid-card-emulated.c | 1 + + hw/usb/ccid-card-passthru.c | 1 + + hw/usb/dev-audio.c | 1 + + hw/usb/dev-bluetooth.c | 1 + + hw/usb/dev-hid.c | 3 +++ + hw/usb/dev-hub.c | 1 + + hw/usb/dev-network.c | 1 + + hw/usb/dev-serial.c | 2 ++ + hw/usb/dev-smartcard-reader.c | 1 + + hw/usb/dev-storage.c | 1 + + hw/usb/dev-uas.c | 1 + + hw/usb/dev-wacom.c | 1 + + hw/usb/hcd-ehci-pci.c | 2 ++ + hw/usb/hcd-ehci-sysbus.c | 5 +++++ + hw/usb/hcd-ohci.c | 2 ++ + hw/usb/hcd-uhci.c | 1 + + hw/usb/hcd-xhci.c | 1 + + hw/usb/host-libusb.c | 1 + + hw/usb/redirect.c | 1 + + hw/virtio/virtio-balloon.c | 1 + + hw/virtio/virtio-pci.c | 8 ++++++++ + hw/virtio/virtio-rng.c | 1 + + hw/watchdog/wdt_i6300esb.c | 1 + + hw/watchdog/wdt_ib700.c | 1 + + hw/xen/xen_platform.c | 1 + + hw/xen/xen_pt.c | 1 + + 105 files changed, 152 insertions(+), 0 deletions(-) + +diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c +index dc6f4e4..69d781d 100644 +--- a/hw/9pfs/virtio-9p-device.c ++++ b/hw/9pfs/virtio-9p-device.c +@@ -141,6 +141,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->props = virtio_9p_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + vdc->init = virtio_9p_device_init; + vdc->get_features = virtio_9p_get_features; + vdc->get_config = virtio_9p_get_config; +diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c +index baf138b..8455a96 100644 +--- a/hw/audio/ac97.c ++++ b/hw/audio/ac97.c +@@ -1418,6 +1418,7 @@ static void ac97_class_init (ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5; + k->revision = 0x01; + k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Intel 82801AA AC97 Audio"; + dc->vmsd = &vmstate_ac97; + dc->props = ac97_properties; +diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c +index fc20857..46934c7 100644 +--- a/hw/audio/adlib.c ++++ b/hw/audio/adlib.c +@@ -361,6 +361,7 @@ static void adlib_class_initfn (ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS (klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS (klass); + ic->init = Adlib_initfn; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = ADLIB_DESC; + dc->props = adlib_properties; + } +diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c +index cc605e5..c970722 100644 +--- a/hw/audio/cs4231a.c ++++ b/hw/audio/cs4231a.c +@@ -677,6 +677,7 @@ static void cs4231a_class_initfn (ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS (klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS (klass); + ic->init = cs4231a_initfn; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Crystal Semiconductor CS4231A"; + dc->vmsd = &vmstate_cs4231a; + dc->props = cs4231a_properties; +diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c +index c1cd169..8678e1e 100644 +--- a/hw/audio/es1370.c ++++ b/hw/audio/es1370.c +@@ -1069,6 +1069,7 @@ static void es1370_class_init (ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; + k->subsystem_vendor_id = 0x4942; + k->subsystem_id = 0x4c4c; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "ENSONIQ AudioPCI ES1370"; + dc->vmsd = &vmstate_es1370; + } +diff --git a/hw/audio/gus.c b/hw/audio/gus.c +index a91921c..3cafca5 100644 +--- a/hw/audio/gus.c ++++ b/hw/audio/gus.c +@@ -312,6 +312,7 @@ static void gus_class_initfn (ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS (klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS (klass); + ic->init = gus_initfn; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Gravis Ultrasound GF1"; + dc->vmsd = &vmstate_gus; + dc->props = gus_properties; +diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c +index 94c472c..07a43bf 100644 +--- a/hw/audio/hda-codec.c ++++ b/hw/audio/hda-codec.c +@@ -638,6 +638,7 @@ static void hda_audio_output_class_init(ObjectClass *klass, void *data) + k->exit = hda_audio_exit; + k->command = hda_audio_command; + k->stream = hda_audio_stream; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "HDA Audio Codec, output-only (line-out)"; + dc->vmsd = &vmstate_hda_audio; + dc->props = hda_audio_properties; +@@ -659,6 +660,7 @@ static void hda_audio_duplex_class_init(ObjectClass *klass, void *data) + k->exit = hda_audio_exit; + k->command = hda_audio_command; + k->stream = hda_audio_stream; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "HDA Audio Codec, duplex (line-out, line-in)"; + dc->vmsd = &vmstate_hda_audio; + dc->props = hda_audio_properties; +@@ -680,6 +682,7 @@ static void hda_audio_micro_class_init(ObjectClass *klass, void *data) + k->exit = hda_audio_exit; + k->command = hda_audio_command; + k->stream = hda_audio_stream; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "HDA Audio Codec, duplex (speaker, microphone)"; + dc->vmsd = &vmstate_hda_audio; + dc->props = hda_audio_properties; +diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c +index 1016af0..e747342 100644 +--- a/hw/audio/intel-hda.c ++++ b/hw/audio/intel-hda.c +@@ -1254,6 +1254,7 @@ static void intel_hda_class_init_ich6(ObjectClass *klass, void *data) + intel_hda_class_init_common(klass); + k->device_id = 0x2668; + k->revision = 1; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Intel HD Audio Controller (ich6)"; + } + +@@ -1265,6 +1266,7 @@ static void intel_hda_class_init_ich9(ObjectClass *klass, void *data) + intel_hda_class_init_common(klass); + k->device_id = 0x293e; + k->revision = 3; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Intel HD Audio Controller (ich9)"; + } + +@@ -1287,6 +1289,7 @@ static void hda_codec_device_class_init(ObjectClass *klass, void *data) + DeviceClass *k = DEVICE_CLASS(klass); + k->init = hda_codec_dev_init; + k->exit = hda_codec_dev_exit; ++ set_bit(DEVICE_CATEGORY_SOUND, k->categories); + k->bus_type = TYPE_HDA_BUS; + k->props = hda_props; + } +diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c +index 3a7285f..4e03bc9 100644 +--- a/hw/audio/pcspk.c ++++ b/hw/audio/pcspk.c +@@ -187,6 +187,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + + ic->init = pcspk_initfn; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->no_user = 1; + dc->props = pcspk_properties; + } +diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c +index 653ab4f..9b11cc9 100644 +--- a/hw/audio/pl041.c ++++ b/hw/audio/pl041.c +@@ -626,6 +626,7 @@ static void pl041_device_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl041_init; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->no_user = 1; + dc->reset = pl041_device_reset; + dc->vmsd = &vmstate_pl041; +diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c +index 6ddc0ac..277bde1 100644 +--- a/hw/audio/sb16.c ++++ b/hw/audio/sb16.c +@@ -1406,6 +1406,7 @@ static void sb16_class_initfn (ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS (klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS (klass); + ic->init = sb16_initfn; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "Creative Sound Blaster 16"; + dc->vmsd = &vmstate_sb16; + dc->props = sb16_properties; +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index 0888652..e292f4c 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2210,6 +2210,7 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data) + dc->reset = fdctrl_external_reset_isa; + dc->vmsd = &vmstate_isa_fdc; + dc->props = isa_fdc_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo isa_fdc_info = { +@@ -2244,6 +2245,7 @@ static void sysbus_fdc_class_init(ObjectClass *klass, void *data) + dc->reset = fdctrl_external_reset_sysbus; + dc->vmsd = &vmstate_sysbus_fdc; + dc->props = sysbus_fdc_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo sysbus_fdc_info = { +@@ -2267,6 +2269,7 @@ static void sun4m_fdc_class_init(ObjectClass *klass, void *data) + dc->reset = fdctrl_external_reset_sysbus; + dc->vmsd = &vmstate_sysbus_fdc; + dc->props = sun4m_fdc_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo sun4m_fdc_info = { +diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c +index 4e3e6b6..0bc5b7a 100644 +--- a/hw/block/pc_sysfw.c ++++ b/hw/block/pc_sysfw.c +@@ -268,6 +268,7 @@ static void pcsysfw_class_init (ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS (klass); + ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->desc = "PC System Firmware"; + dc->init = pcsysfw_init; + dc->props = pcsysfw_properties; +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 3ff20e0..0bbb1a3 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -715,6 +715,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data) + k->init = pflash_cfi01_init; + dc->props = pflash_cfi01_properties; + dc->vmsd = &vmstate_pflash; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index ce1a523..9fe622d 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -756,6 +756,7 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_blk_device_exit; + dc->props = virtio_blk_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + vdc->init = virtio_blk_device_init; + vdc->get_config = virtio_blk_update_config; + vdc->set_config = virtio_blk_set_config; +diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c +index 02c9577..b974889 100644 +--- a/hw/char/debugcon.c ++++ b/hw/char/debugcon.c +@@ -117,6 +117,7 @@ static void debugcon_isa_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = debugcon_isa_initfn; + dc->props = debugcon_isa_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo debugcon_isa_info = { +diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c +index 2a2c230..a11b9c2 100644 +--- a/hw/char/imx_serial.c ++++ b/hw/char/imx_serial.c +@@ -448,6 +448,7 @@ static void imx_serial_class_init(ObjectClass *klass, void *data) + k->init = imx_serial_init; + dc->vmsd = &vmstate_imx_serial; + dc->reset = imx_serial_reset_at_boot; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "i.MX series UART"; + dc->props = imx32_serial_properties; + } +diff --git a/hw/char/ipack.c b/hw/char/ipack.c +index e15540d..f890471 100644 +--- a/hw/char/ipack.c ++++ b/hw/char/ipack.c +@@ -74,6 +74,7 @@ static Property ipack_device_props[] = { + static void ipack_device_class_init(ObjectClass *klass, void *data) + { + DeviceClass *k = DEVICE_CLASS(klass); ++ set_bit(DEVICE_CATEGORY_INPUT, k->categories); + k->bus_type = TYPE_IPACK_BUS; + k->init = ipack_device_dev_init; + k->exit = ipack_device_dev_exit; +diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c +index c9698a6..88e2cca 100644 +--- a/hw/char/ipoctal232.c ++++ b/hw/char/ipoctal232.c +@@ -585,6 +585,7 @@ static void ipoctal_class_init(ObjectClass *klass, void *data) + ic->mem_read8 = mem_read8; + ic->mem_write8 = mem_write8; + ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "GE IP-Octal 232 8-channel RS-232 IndustryPack"; + dc->props = ipoctal_properties; + dc->vmsd = &vmstate_ipoctal; +diff --git a/hw/char/parallel.c b/hw/char/parallel.c +index 8e48284..046e453 100644 +--- a/hw/char/parallel.c ++++ b/hw/char/parallel.c +@@ -602,6 +602,7 @@ static void parallel_isa_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = parallel_isa_initfn; + dc->props = parallel_isa_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo parallel_isa_info = { +diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c +index 342b4cc..cc00544 100644 +--- a/hw/char/serial-isa.c ++++ b/hw/char/serial-isa.c +@@ -100,6 +100,7 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data) + ic->init = serial_isa_initfn; + dc->vmsd = &vmstate_isa_serial; + dc->props = serial_isa_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo serial_isa_info = { +diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c +index 2138e35..77fec01 100644 +--- a/hw/char/serial-pci.c ++++ b/hw/char/serial-pci.c +@@ -191,6 +191,7 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data) + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_serial; + dc->props = serial_pci_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data) +@@ -205,6 +206,7 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data) + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_2x_serial_pci_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) +@@ -219,6 +221,7 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_4x_serial_pci_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo serial_pci_info = { +diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c +index 0170602..cc6a963 100644 +--- a/hw/char/tpci200.c ++++ b/hw/char/tpci200.c +@@ -652,6 +652,7 @@ static void tpci200_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_BRIDGE_OTHER; + k->subsystem_vendor_id = PCI_VENDOR_ID_TEWS; + k->subsystem_id = 0x300A; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "TEWS TPCI200 IndustryPack carrier"; + dc->vmsd = &vmstate_tpci200; + } +diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c +index cc3d1dd..da417c7 100644 +--- a/hw/char/virtio-serial-bus.c ++++ b/hw/char/virtio-serial-bus.c +@@ -971,6 +971,7 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) + { + DeviceClass *k = DEVICE_CLASS(klass); + k->init = virtser_port_qdev_init; ++ set_bit(DEVICE_CATEGORY_INPUT, k->categories); + k->bus_type = TYPE_VIRTIO_SERIAL_BUS; + k->exit = virtser_port_qdev_exit; + k->unplug = qdev_simple_unplug_cb; +@@ -1017,6 +1018,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_serial_device_exit; + dc->props = virtio_serial_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + vdc->init = virtio_serial_device_init; + vdc->get_features = get_features; + vdc->get_config = get_config; +diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c +index 73a1dc9..4df814b 100644 +--- a/hw/cpu/icc_bus.c ++++ b/hw/cpu/icc_bus.c +@@ -101,11 +101,19 @@ static void icc_bridge_init(Object *obj) + s->icc_bus.apic_address_space = &s->apic_container; + } + ++static void icc_bridge_class_init(ObjectClass *oc, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(oc); ++ ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); ++} ++ + static const TypeInfo icc_bridge_info = { + .name = TYPE_ICC_BRIDGE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = icc_bridge_init, + .instance_size = sizeof(ICCBridgeState), ++ .class_init = icc_bridge_class_init, + }; + + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index fa8eae2..a7634ba 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -2936,6 +2936,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_cirrus_vga; + k->init = vga_initfn; + dc->props = isa_cirrus_vga_properties; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + } + + static const TypeInfo isa_cirrus_vga_info = { +@@ -3001,6 +3002,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_CIRRUS; + k->device_id = CIRRUS_ID_CLGD5446; + k->class_id = PCI_CLASS_DISPLAY_VGA; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->desc = "Cirrus CLGD 54xx VGA"; + dc->vmsd = &vmstate_pci_cirrus_vga; + dc->props = pci_vga_cirrus_properties; +diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c +index 2a4047e..2b974ca 100644 +--- a/hw/display/g364fb.c ++++ b/hw/display/g364fb.c +@@ -528,6 +528,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = g364fb_sysbus_init; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->desc = "G364 framebuffer"; + dc->reset = g364fb_sysbus_reset; + dc->vmsd = &vmstate_g364fb; +diff --git a/hw/display/pl110.c b/hw/display/pl110.c +index f259955..b45a7be 100644 +--- a/hw/display/pl110.c ++++ b/hw/display/pl110.c +@@ -481,6 +481,7 @@ static void pl110_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl110_init; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->no_user = 1; + dc->vmsd = &vmstate_pl110; + } +@@ -498,6 +499,7 @@ static void pl110_versatile_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl110_versatile_init; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->no_user = 1; + dc->vmsd = &vmstate_pl110; + } +@@ -515,6 +517,7 @@ static void pl111_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl111_init; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->no_user = 1; + dc->vmsd = &vmstate_pl110; + } +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index 937a402..ea985d2 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -2317,6 +2317,7 @@ static void qxl_primary_class_init(ObjectClass *klass, void *data) + k->vendor_id = REDHAT_PCI_VENDOR_ID; + k->device_id = QXL_DEVICE_ID_STABLE; + k->class_id = PCI_CLASS_DISPLAY_VGA; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->desc = "Spice QXL GPU (primary, vga compatible)"; + dc->reset = qxl_reset_handler; + dc->vmsd = &qxl_vmstate; +@@ -2339,6 +2340,7 @@ static void qxl_secondary_class_init(ObjectClass *klass, void *data) + k->vendor_id = REDHAT_PCI_VENDOR_ID; + k->device_id = QXL_DEVICE_ID_STABLE; + k->class_id = PCI_CLASS_DISPLAY_OTHER; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->desc = "Spice QXL GPU (secondary)"; + dc->reset = qxl_reset_handler; + dc->vmsd = &qxl_vmstate; +diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c +index 2f34ee3..775b800 100644 +--- a/hw/display/vga-isa.c ++++ b/hw/display/vga-isa.c +@@ -88,6 +88,7 @@ static void vga_isa_class_initfn(ObjectClass *klass, void *data) + dc->reset = vga_isa_reset; + dc->vmsd = &vmstate_vga_common; + dc->props = vga_isa_properties; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + } + + static const TypeInfo vga_isa_info = { +diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c +index cea8db7..21aa4bf 100644 +--- a/hw/display/vga-pci.c ++++ b/hw/display/vga-pci.c +@@ -197,6 +197,7 @@ static void vga_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_DISPLAY_VGA; + dc->vmsd = &vmstate_vga_pci; + dc->props = vga_pci_properties; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + } + + static const TypeInfo vga_info = { +diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c +index fd3569d..df76aec 100644 +--- a/hw/display/vmware_vga.c ++++ b/hw/display/vmware_vga.c +@@ -1296,6 +1296,7 @@ static void vmsvga_class_init(ObjectClass *klass, void *data) + dc->reset = vmsvga_reset; + dc->vmsd = &vmstate_vmware_vga; + dc->props = vga_vmware_properties; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + } + + static const TypeInfo vmsvga_info = { +diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c +index 854b8e1..f5e4836 100644 +--- a/hw/i2c/bitbang_i2c.c ++++ b/hw/i2c/bitbang_i2c.c +@@ -227,6 +227,7 @@ static void gpio_i2c_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = gpio_i2c_init; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "Virtual GPIO to I2C bridge"; + } + +diff --git a/hw/i2c/core.c b/hw/i2c/core.c +index 0c4fc1d..ef3b000 100644 +--- a/hw/i2c/core.c ++++ b/hw/i2c/core.c +@@ -224,6 +224,7 @@ static void i2c_slave_class_init(ObjectClass *klass, void *data) + { + DeviceClass *k = DEVICE_CLASS(klass); + k->init = i2c_slave_qdev_init; ++ set_bit(DEVICE_CATEGORY_MISC, k->categories); + k->bus_type = TYPE_I2C_BUS; + k->props = i2c_props; + } +diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c +index c1e08ec..1684f8c 100644 +--- a/hw/i386/kvm/pci-assign.c ++++ b/hw/i386/kvm/pci-assign.c +@@ -1835,6 +1835,7 @@ static void assign_class_init(ObjectClass *klass, void *data) + dc->props = assigned_dev_properties; + dc->vmsd = &vmstate_assigned_device; + dc->reset = reset_assigned_device; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->desc = "KVM-based PCI passthrough"; + } + +diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c +index ade9f64..011e796 100644 +--- a/hw/ide/ahci.c ++++ b/hw/ide/ahci.c +@@ -1326,6 +1326,7 @@ static void sysbus_ahci_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_sysbus_ahci; + dc->props = sysbus_ahci_properties; + dc->reset = sysbus_ahci_reset; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo sysbus_ahci_info = { +diff --git a/hw/ide/ich.c b/hw/ide/ich.c +index ed1f1a2..4d53564 100644 +--- a/hw/ide/ich.c ++++ b/hw/ide/ich.c +@@ -160,6 +160,7 @@ static void ich_ahci_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_STORAGE_SATA; + dc->vmsd = &vmstate_ich9_ahci; + dc->reset = pci_ich9_reset; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo ich_ahci_info = { +diff --git a/hw/ide/isa.c b/hw/ide/isa.c +index 369a7fa..2a14260 100644 +--- a/hw/ide/isa.c ++++ b/hw/ide/isa.c +@@ -118,6 +118,7 @@ static void isa_ide_class_initfn(ObjectClass *klass, void *data) + dc->fw_name = "ide"; + dc->reset = isa_ide_reset; + dc->props = isa_ide_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo isa_ide_info = { +diff --git a/hw/ide/piix.c b/hw/ide/piix.c +index bf2856f..8d4bf2f 100644 +--- a/hw/ide/piix.c ++++ b/hw/ide/piix.c +@@ -248,6 +248,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->no_user = 1; + } + +@@ -267,6 +268,7 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->no_user = 1; + dc->unplug = pci_piix3_xen_ide_unplug; + } +@@ -289,6 +291,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371AB; + k->class_id = PCI_CLASS_STORAGE_IDE; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->no_user = 1; + } + +diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c +index 6a272b0..1d84e15 100644 +--- a/hw/ide/qdev.c ++++ b/hw/ide/qdev.c +@@ -282,6 +282,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data) + { + DeviceClass *k = DEVICE_CLASS(klass); + k->init = ide_qdev_init; ++ set_bit(DEVICE_CATEGORY_STORAGE, k->categories); + k->bus_type = TYPE_IDE_BUS; + k->props = ide_props; + } +diff --git a/hw/ide/via.c b/hw/ide/via.c +index 5fe053c..30dedd8 100644 +--- a/hw/ide/via.c ++++ b/hw/ide/via.c +@@ -223,6 +223,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_VIA_IDE; + k->revision = 0x06; + k->class_id = PCI_CLASS_STORAGE_IDE; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->no_user = 1; + } + +diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c +index cced9af..3c62519 100644 +--- a/hw/isa/i82378.c ++++ b/hw/isa/i82378.c +@@ -259,6 +259,7 @@ static void pci_i82378_class_init(ObjectClass *klass, void *data) + k->subsystem_vendor_id = 0x0; + k->subsystem_id = 0x0; + dc->vmsd = &vmstate_pci_i82378; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->props = i82378_properties; + } + +diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c +index 667e882..2760dce 100644 +--- a/hw/isa/lpc_ich9.c ++++ b/hw/isa/lpc_ich9.c +@@ -599,6 +599,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->reset = ich9_lpc_reset; + k->init = ich9_lpc_initfn; + dc->vmsd = &vmstate_ich9_lpc; +diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c +index 5261927..79057a6 100644 +--- a/hw/isa/vt82c686.c ++++ b/hw/isa/vt82c686.c +@@ -279,6 +279,7 @@ static void via_ac97_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_VIA_AC97; + k->revision = 0x50; + k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + dc->desc = "AC97"; + } + +@@ -320,6 +321,7 @@ static void via_mc97_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_VIA_MC97; + k->class_id = PCI_CLASS_COMMUNICATION_OTHER; + k->revision = 0x30; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "MC97"; + } + +@@ -399,6 +401,7 @@ static void via_pm_class_init(ObjectClass *klass, void *data) + k->revision = 0x40; + dc->desc = "PM"; + dc->vmsd = &vmstate_acpi; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->props = via_pm_properties; + } + +diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c +index 78904a8..69f3cd0 100644 +--- a/hw/misc/applesmc.c ++++ b/hw/misc/applesmc.c +@@ -239,6 +239,7 @@ static void qdev_applesmc_class_init(ObjectClass *klass, void *data) + ic->init = applesmc_isa_init; + dc->reset = qdev_applesmc_isa_reset; + dc->props = applesmc_isa_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo applesmc_isa_info = { +diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c +index 59bed5b..9fd72ec 100644 +--- a/hw/misc/debugexit.c ++++ b/hw/misc/debugexit.c +@@ -58,6 +58,7 @@ static void debug_exit_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = debug_exit_initfn; + dc->props = debug_exit_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo debug_exit_info = { +diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c +index 5658f73..5acef7a 100644 +--- a/hw/misc/ivshmem.c ++++ b/hw/misc/ivshmem.c +@@ -810,6 +810,7 @@ static void ivshmem_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_MEMORY_RAM; + dc->reset = ivshmem_reset; + dc->props = ivshmem_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo ivshmem_info = { +diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c +index 32df175..cae8d70 100644 +--- a/hw/misc/pc-testdev.c ++++ b/hw/misc/pc-testdev.c +@@ -167,9 +167,11 @@ static int init_test_device(ISADevice *isa) + + static void testdev_class_init(ObjectClass *klass, void *data) + { ++ DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *k = ISA_DEVICE_CLASS(klass); + + k->init = init_test_device; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo testdev_info = { +diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c +index 71ce5a3..b11bc5f 100644 +--- a/hw/misc/pci-testdev.c ++++ b/hw/misc/pci-testdev.c +@@ -307,6 +307,7 @@ static void pci_testdev_class_init(ObjectClass *klass, void *data) + k->revision = 0x00; + k->class_id = PCI_CLASS_OTHERS; + dc->desc = "PCI Test Device"; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->reset = qdev_pci_testdev_reset; + } + +diff --git a/hw/misc/sga.c b/hw/misc/sga.c +index c842190..5ea124b 100644 +--- a/hw/misc/sga.c ++++ b/hw/misc/sga.c +@@ -49,6 +49,7 @@ static void sga_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = sga_initfn; ++ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); + dc->desc = "Serial Graphics Adapter"; + } + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index f8fef8c..a966c58 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3309,6 +3309,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) + dc->props = vfio_pci_dev_properties; + dc->vmsd = &vfio_pci_vmstate; + dc->desc = "VFIO-based PCI device assignment"; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + pdc->init = vfio_initfn; + pdc->exit = vfio_exitfn; + pdc->config_read = vfio_pci_read_config; +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index 76df2f3..a813523 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1393,6 +1393,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) + k->device_id = E1000_DEVID; + k->revision = 0x03; + k->class_id = PCI_CLASS_NETWORK_ETHERNET; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "Intel Gigabit Ethernet"; + dc->reset = qdev_e1000_reset; + dc->vmsd = &vmstate_e1000; +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index b69cc60..5190f88 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -2083,6 +2083,7 @@ static void eepro100_class_init(ObjectClass *klass, void *data) + + info = eepro100_get_class_by_name(object_class_get_name(klass)); + ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->props = e100_properties; + dc->desc = info->desc; + k->vendor_id = PCI_VENDOR_ID_INTEL; +diff --git a/hw/net/lance.c b/hw/net/lance.c +index 187497c..90641e7 100644 +--- a/hw/net/lance.c ++++ b/hw/net/lance.c +@@ -149,6 +149,7 @@ static void lance_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = lance_init; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->fw_name = "ethernet"; + dc->reset = lance_reset; + dc->vmsd = &vmstate_lance; +diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c +index ac6193a..52cb4ff 100644 +--- a/hw/net/mipsnet.c ++++ b/hw/net/mipsnet.c +@@ -263,6 +263,7 @@ static void mipsnet_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = mipsnet_sysbus_init; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "MIPS Simulator network device"; + dc->reset = mipsnet_sysbus_reset; + dc->vmsd = &vmstate_mipsnet; +diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c +index f8e610c..877a6b1 100644 +--- a/hw/net/ne2000-isa.c ++++ b/hw/net/ne2000-isa.c +@@ -99,6 +99,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = isa_ne2000_initfn; + dc->props = ne2000_isa_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo ne2000_isa_info = { +diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c +index 94d6110..b401cb8 100644 +--- a/hw/net/ne2000.c ++++ b/hw/net/ne2000.c +@@ -772,6 +772,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_NETWORK_ETHERNET; + dc->vmsd = &vmstate_pci_ne2000; + dc->props = ne2000_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo ne2000_info = { +diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c +index be64bf2..7491718 100644 +--- a/hw/net/opencores_eth.c ++++ b/hw/net/opencores_eth.c +@@ -713,6 +713,7 @@ static void open_eth_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = sysbus_open_eth_init; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "Opencores 10/100 Mbit Ethernet"; + dc->reset = qdev_open_eth_reset; + dc->props = open_eth_properties; +diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c +index e07f388..befc6ce 100644 +--- a/hw/net/pcnet-pci.c ++++ b/hw/net/pcnet-pci.c +@@ -359,6 +359,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data) + dc->reset = pci_reset; + dc->vmsd = &vmstate_pci_pcnet; + dc->props = pcnet_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo pcnet_info = { +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 1e5a679..8f20ef4 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -3541,6 +3541,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data) + dc->reset = rtl8139_reset; + dc->vmsd = &vmstate_rtl8139; + dc->props = rtl8139_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo rtl8139_info = { +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index bed0822..9ebcdfe 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -1448,6 +1448,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_net_device_exit; + dc->props = virtio_net_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + vdc->init = virtio_net_device_init; + vdc->get_config = virtio_net_get_config; + vdc->set_config = virtio_net_set_config; +diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c +index 4c575e5..d43284a 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -2453,6 +2453,7 @@ static void vmxnet3_class_init(ObjectClass *class, void *data) + dc->reset = vmxnet3_qdev_reset; + dc->vmsd = &vmstate_vmxnet3; + dc->props = vmxnet3_properties; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo vmxnet3_info = { +diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c +index 0841531..21b3225 100644 +--- a/hw/pci-bridge/i82801b11.c ++++ b/hw/pci-bridge/i82801b11.c +@@ -81,6 +81,7 @@ err_bridge: + static void i82801b11_bridge_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->is_bridge = 1; + k->vendor_id = PCI_VENDOR_ID_INTEL; +@@ -88,6 +89,7 @@ static void i82801b11_bridge_class_init(ObjectClass *klass, void *data) + k->revision = ICH9_D2P_A2_REVISION; + k->init = i82801b11_bridge_initfn; + k->config_write = pci_bridge_write_config; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + } + + static const TypeInfo i82801b11_bridge_info = { +diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c +index bb541eb..47122c5 100644 +--- a/hw/pci-bridge/ioh3420.c ++++ b/hw/pci-bridge/ioh3420.c +@@ -220,6 +220,7 @@ static void ioh3420_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_IOH_EPORT; + k->revision = PCI_DEVICE_ID_IOH_REV; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "Intel IOH device id 3420 PCIE Root Port"; + dc->reset = ioh3420_reset; + dc->vmsd = &vmstate_ioh3420; +diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c +index 971b432..43f94fc 100644 +--- a/hw/pci-bridge/pci_bridge_dev.c ++++ b/hw/pci-bridge/pci_bridge_dev.c +@@ -141,6 +141,7 @@ static void pci_bridge_dev_class_init(ObjectClass *klass, void *data) + dc->reset = qdev_pci_bridge_dev_reset; + dc->props = pci_bridge_dev_properties; + dc->vmsd = &pci_bridge_dev_vmstate; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + } + + static const TypeInfo pci_bridge_dev_info = { +diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c +index 1810dd2..33eff37 100644 +--- a/hw/pci-bridge/xio3130_downstream.c ++++ b/hw/pci-bridge/xio3130_downstream.c +@@ -187,6 +187,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_TI; + k->device_id = PCI_DEVICE_ID_TI_XIO3130D; + k->revision = XIO3130_REVISION; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "TI X3130 Downstream Port of PCI Express Switch"; + dc->reset = xio3130_downstream_reset; + dc->vmsd = &vmstate_xio3130_downstream; +diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c +index 8e0d97a..e9969a9 100644 +--- a/hw/pci-bridge/xio3130_upstream.c ++++ b/hw/pci-bridge/xio3130_upstream.c +@@ -161,6 +161,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_TI; + k->device_id = PCI_DEVICE_ID_TI_XIO3130U; + k->revision = XIO3130_REVISION; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "TI X3130 Upstream Port of PCI Express Switch"; + dc->reset = xio3130_upstream_reset; + dc->vmsd = &vmstate_xio3130_upstream; +diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c +index e099655..5ac7556 100644 +--- a/hw/pci-host/apb.c ++++ b/hw/pci-host/apb.c +@@ -577,6 +577,7 @@ static void pbm_host_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pci_pbm_init_device; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->reset = pci_pbm_reset; + } + +@@ -599,6 +600,7 @@ static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data) + k->revision = 0x11; + k->config_write = pci_bridge_write_config; + k->is_bridge = 1; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->reset = pci_bridge_reset; + dc->vmsd = &vmstate_pci_device; + } +diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c +index 5e7ad94..0d0a001 100644 +--- a/hw/pci-host/ppce500.c ++++ b/hw/pci-host/ppce500.c +@@ -407,6 +407,7 @@ static void e500_pcihost_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = e500_pcihost_initfn; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->props = pcihost_properties; + dc->vmsd = &vmstate_ppce500_pci; + } +diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c +index 6130253..8c4e6eb 100644 +--- a/hw/pci-host/prep.c ++++ b/hw/pci-host/prep.c +@@ -210,6 +210,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize = raven_pcihost_realizefn; + dc->fw_name = "pci"; + dc->no_user = 1; +diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c +index 24df6b5..5f8e7ff 100644 +--- a/hw/pci-host/q35.c ++++ b/hw/pci-host/q35.c +@@ -76,6 +76,7 @@ static void q35_host_class_init(ObjectClass *klass, void *data) + + k->init = q35_host_init; + dc->props = mch_props; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->fw_name = "pci"; + } + +@@ -287,6 +288,7 @@ static void mch_class_init(ObjectClass *klass, void *data) + k->init = mch_init; + k->config_write = mch_write_config; + dc->reset = mch_reset; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->desc = "Host bridge"; + dc->vmsd = &vmstate_mch; + k->vendor_id = PCI_VENDOR_ID_INTEL; +diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c +index 029789a..0be165f 100644 +--- a/hw/scsi/esp-pci.c ++++ b/hw/scsi/esp-pci.c +@@ -379,6 +379,7 @@ static void esp_pci_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_AMD_SCSI; + k->revision = 0x10; + k->class_id = PCI_CLASS_STORAGE_SCSI; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->desc = "AMD Am53c974 PCscsi-PCI SCSI adapter"; + dc->reset = esp_pci_hard_reset; + dc->vmsd = &vmstate_esp_pci_scsi; +@@ -499,6 +500,7 @@ static void dc390_class_init(ObjectClass *klass, void *data) + k->init = dc390_scsi_init; + k->config_read = dc390_read_config; + k->config_write = dc390_write_config; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->desc = "Tekram DC-390 SCSI adapter"; + } + +diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c +index 0c81a50..a1a7279 100644 +--- a/hw/scsi/esp.c ++++ b/hw/scsi/esp.c +@@ -710,6 +710,7 @@ static void sysbus_esp_class_init(ObjectClass *klass, void *data) + k->init = sysbus_esp_init; + dc->reset = sysbus_esp_hard_reset; + dc->vmsd = &vmstate_sysbus_esp_scsi; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo sysbus_esp_info = { +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 22b8e98..2e322d7 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -2119,6 +2119,7 @@ static void lsi_class_init(ObjectClass *klass, void *data) + k->subsystem_id = 0x1000; + dc->reset = lsi_scsi_reset; + dc->vmsd = &vmstate_lsi_scsi; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static const TypeInfo lsi_info = { +diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c +index 27288b9..d916a81 100644 +--- a/hw/scsi/megasas.c ++++ b/hw/scsi/megasas.c +@@ -2198,6 +2198,7 @@ static void megasas_class_init(ObjectClass *oc, void *data) + dc->props = megasas_properties; + dc->reset = megasas_scsi_reset; + dc->vmsd = &vmstate_megasas; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->desc = "LSI MegaRAID SAS 1078"; + } + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 0885d9d..18a0399 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -1865,6 +1865,7 @@ const VMStateDescription vmstate_scsi_device = { + static void scsi_device_class_init(ObjectClass *klass, void *data) + { + DeviceClass *k = DEVICE_CLASS(klass); ++ set_bit(DEVICE_CATEGORY_STORAGE, k->categories); + k->bus_type = TYPE_SCSI_BUS; + k->init = scsi_qdev_init; + k->unplug = scsi_qdev_unplug; +diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c +index 785e93f..9e770fb 100644 +--- a/hw/scsi/vhost-scsi.c ++++ b/hw/scsi/vhost-scsi.c +@@ -267,6 +267,7 @@ static void vhost_scsi_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = vhost_scsi_exit; + dc->props = vhost_scsi_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + vdc->init = vhost_scsi_init; + vdc->get_features = vhost_scsi_get_features; + vdc->set_config = vhost_scsi_set_config; +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 4074088..038cd83 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -662,8 +662,10 @@ static Property virtio_scsi_properties[] = { + static void virtio_scsi_common_class_init(ObjectClass *klass, void *data) + { + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + vdc->get_config = virtio_scsi_get_config; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + } + + static void virtio_scsi_class_init(ObjectClass *klass, void *data) +@@ -672,6 +674,7 @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_scsi_device_exit; + dc->props = virtio_scsi_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + vdc->init = virtio_scsi_device_init; + vdc->set_config = virtio_scsi_set_config; + vdc->get_features = virtio_scsi_get_features; +diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c +index 48d12f4..8600a18 100644 +--- a/hw/scsi/vmw_pvscsi.c ++++ b/hw/scsi/vmw_pvscsi.c +@@ -1197,6 +1197,7 @@ static void pvscsi_class_init(ObjectClass *klass, void *data) + dc->reset = pvscsi_reset; + dc->vmsd = &vmstate_pvscsi; + dc->props = pvscsi_properties; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + k->config_write = pvscsi_write_config; + } + +diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c +index deb6d47..aa913df 100644 +--- a/hw/usb/ccid-card-emulated.c ++++ b/hw/usb/ccid-card-emulated.c +@@ -592,6 +592,7 @@ static void emulated_class_initfn(ObjectClass *klass, void *data) + cc->exitfn = emulated_exitfn; + cc->get_atr = emulated_get_atr; + cc->apdu_from_guest = emulated_apdu_from_guest; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "emulated smartcard"; + dc->props = emulated_card_properties; + } +diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c +index 01c7e6f..c1d20c0 100644 +--- a/hw/usb/ccid-card-passthru.c ++++ b/hw/usb/ccid-card-passthru.c +@@ -392,6 +392,7 @@ static void passthru_class_initfn(ObjectClass *klass, void *data) + cc->exitfn = passthru_exitfn; + cc->get_atr = passthru_get_atr; + cc->apdu_from_guest = passthru_apdu_from_guest; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "passthrough smartcard"; + dc->vmsd = &passthru_vmstate; + dc->props = passthru_card_properties; +diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c +index 04933a9..c5420eb 100644 +--- a/hw/usb/dev-audio.c ++++ b/hw/usb/dev-audio.c +@@ -673,6 +673,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data) + + dc->vmsd = &vmstate_usb_audio; + dc->props = usb_audio_properties; ++ set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + k->product_desc = "QEMU USB Audio Interface"; + k->usb_desc = &desc_audio; + k->init = usb_audio_initfn; +diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c +index 786e30e..7f292b1 100644 +--- a/hw/usb/dev-bluetooth.c ++++ b/hw/usb/dev-bluetooth.c +@@ -560,6 +560,7 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data) + uc->handle_data = usb_bt_handle_data; + uc->handle_destroy = usb_bt_handle_destroy; + dc->vmsd = &vmstate_usb_bt; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + } + + static const TypeInfo bt_info = { +diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c +index 31f3cde..66c6331 100644 +--- a/hw/usb/dev-hid.c ++++ b/hw/usb/dev-hid.c +@@ -658,6 +658,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) + uc->product_desc = "QEMU USB Tablet"; + dc->vmsd = &vmstate_usb_ptr; + dc->props = usb_tablet_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo usb_tablet_info = { +@@ -677,6 +678,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data) + uc->product_desc = "QEMU USB Mouse"; + uc->usb_desc = &desc_mouse; + dc->vmsd = &vmstate_usb_ptr; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo usb_mouse_info = { +@@ -696,6 +698,7 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) + uc->product_desc = "QEMU USB Keyboard"; + uc->usb_desc = &desc_keyboard; + dc->vmsd = &vmstate_usb_kbd; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo usb_keyboard_info = { +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index a5f092b..4188a3c 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -570,6 +570,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data) + uc->handle_control = usb_hub_handle_control; + uc->handle_data = usb_hub_handle_data; + uc->handle_destroy = usb_hub_handle_destroy; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->fw_name = "hub"; + dc->vmsd = &vmstate_usb_hub; + } +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 5473ac2..660d774 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1429,6 +1429,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data) + uc->handle_control = usb_net_handle_control; + uc->handle_data = usb_net_handle_data; + uc->handle_destroy = usb_net_handle_destroy; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->fw_name = "network"; + dc->vmsd = &vmstate_usb_net; + dc->props = net_properties; +diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c +index 2fc8a3b..0b150d4 100644 +--- a/hw/usb/dev-serial.c ++++ b/hw/usb/dev-serial.c +@@ -590,6 +590,7 @@ static void usb_serial_class_initfn(ObjectClass *klass, void *data) + uc->handle_data = usb_serial_handle_data; + dc->vmsd = &vmstate_usb_serial; + dc->props = serial_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo serial_info = { +@@ -617,6 +618,7 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data) + uc->handle_data = usb_serial_handle_data; + dc->vmsd = &vmstate_usb_serial; + dc->props = braille_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo braille_info = { +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index 125cc2c..c1acf70 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -1449,6 +1449,7 @@ static void ccid_class_initfn(ObjectClass *klass, void *data) + dc->desc = "CCID Rev 1.1 smartcard reader"; + dc->vmsd = &ccid_vmstate; + dc->props = ccid_properties; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + } + + static const TypeInfo ccid_info = { +diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c +index fe914ab..44a0e34 100644 +--- a/hw/usb/dev-storage.c ++++ b/hw/usb/dev-storage.c +@@ -744,6 +744,7 @@ static void usb_msd_class_initfn_common(ObjectClass *klass) + uc->handle_reset = usb_msd_handle_reset; + uc->handle_control = usb_msd_handle_control; + uc->handle_data = usb_msd_handle_data; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->fw_name = "storage"; + dc->vmsd = &vmstate_usb_msd; + } +diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c +index 6efab62..63ad12e 100644 +--- a/hw/usb/dev-uas.c ++++ b/hw/usb/dev-uas.c +@@ -916,6 +916,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data) + uc->handle_control = usb_uas_handle_control; + uc->handle_data = usb_uas_handle_data; + uc->handle_destroy = usb_uas_handle_destroy; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->fw_name = "storage"; + dc->vmsd = &vmstate_usb_uas; + } +diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c +index 3be5cde..1b09235 100644 +--- a/hw/usb/dev-wacom.c ++++ b/hw/usb/dev-wacom.c +@@ -362,6 +362,7 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data) + uc->handle_control = usb_wacom_handle_control; + uc->handle_data = usb_wacom_handle_data; + uc->handle_destroy = usb_wacom_handle_destroy; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "QEMU PenPartner Tablet"; + dc->vmsd = &vmstate_usb_wacom; + } +diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c +index 0eb7826..2f9aa0e 100644 +--- a/hw/usb/hcd-ehci-pci.c ++++ b/hw/usb/hcd-ehci-pci.c +@@ -129,11 +129,13 @@ static const TypeInfo ehci_pci_type_info = { + static void ehci_data_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + EHCIPCIInfo *i = data; + + k->vendor_id = i->vendor_id; + k->device_id = i->device_id; + k->revision = i->revision; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + } + + static struct EHCIPCIInfo ehci_pci_info[] = { +diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c +index b68a66a..b0b25d4 100644 +--- a/hw/usb/hcd-ehci-sysbus.c ++++ b/hw/usb/hcd-ehci-sysbus.c +@@ -56,6 +56,7 @@ static void ehci_sysbus_class_init(ObjectClass *klass, void *data) + k->init = usb_ehci_sysbus_initfn; + dc->vmsd = &vmstate_ehci_sysbus; + dc->props = ehci_sysbus_properties; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + } + + static const TypeInfo ehci_type_info = { +@@ -70,7 +71,9 @@ static const TypeInfo ehci_type_info = { + static void ehci_xlnx_class_init(ObjectClass *oc, void *data) + { + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); ++ DeviceClass *dc = DEVICE_CLASS(oc); + ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + sec->capsbase = 0x100; + sec->opregbase = 0x140; + } +@@ -84,9 +87,11 @@ static const TypeInfo ehci_xlnx_type_info = { + static void ehci_exynos4210_class_init(ObjectClass *oc, void *data) + { + SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc); ++ DeviceClass *dc = DEVICE_CLASS(oc); + + sec->capsbase = 0x0; + sec->opregbase = 0x10; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + } + + static const TypeInfo ehci_exynos4210_type_info = { +diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c +index 51241cd..c8d1420 100644 +--- a/hw/usb/hcd-ohci.c ++++ b/hw/usb/hcd-ohci.c +@@ -1906,6 +1906,7 @@ static void ohci_pci_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB; + k->class_id = PCI_CLASS_SERIAL_USB; + k->no_hotplug = 1; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + dc->desc = "Apple USB Controller"; + dc->props = ohci_pci_properties; + } +@@ -1929,6 +1930,7 @@ static void ohci_sysbus_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); + + sbc->init = ohci_init_pxa; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + dc->desc = "OHCI USB Controller"; + dc->props = ohci_sysbus_properties; + } +diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c +index c85b203..4fc3410 100644 +--- a/hw/usb/hcd-uhci.c ++++ b/hw/usb/hcd-uhci.c +@@ -1313,6 +1313,7 @@ static void uhci_class_init(ObjectClass *klass, void *data) + k->no_hotplug = 1; + dc->vmsd = &vmstate_uhci; + dc->props = uhci_properties; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + u->info = *info; + } + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 0061cbe..9d7315f 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -3611,6 +3611,7 @@ static void xhci_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_xhci; + dc->props = xhci_properties; + dc->reset = xhci_reset; ++ set_bit(DEVICE_CATEGORY_USB, dc->categories); + k->init = usb_xhci_initfn; + k->vendor_id = PCI_VENDOR_ID_NEC; + k->device_id = PCI_DEVICE_ID_NEC_UPD720200; +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index e2f3cc8..f660770 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1351,6 +1351,7 @@ static void usb_host_class_initfn(ObjectClass *klass, void *data) + uc->flush_ep_queue = usb_host_flush_ep_queue; + dc->vmsd = &vmstate_usb_host; + dc->props = usb_host_dev_properties; ++ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + } + + static TypeInfo usb_host_dev_info = { +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index a594e95..8b8c010 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -2362,6 +2362,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) + uc->ep_stopped = usbredir_ep_stopped; + dc->vmsd = &usbredir_vmstate; + dc->props = usbredir_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo usbredir_dev_info = { +diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c +index d669756..85661f6 100644 +--- a/hw/virtio/virtio-balloon.c ++++ b/hw/virtio/virtio-balloon.c +@@ -391,6 +391,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_balloon_device_exit; + dc->props = virtio_balloon_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->init = virtio_balloon_device_init; + vdc->get_config = virtio_balloon_get_config; + vdc->set_config = virtio_balloon_set_config; +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index d82f6ff..ba8848f 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -917,6 +917,7 @@ static void virtio_9p_pci_class_init(ObjectClass *klass, void *data) + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_9P; + pcidev_k->revision = VIRTIO_PCI_ABI_VERSION; + pcidev_k->class_id = 0x2; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->props = virtio_9p_pci_properties; + } + +@@ -1071,6 +1072,7 @@ static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->props = virtio_blk_pci_properties; + k->init = virtio_blk_pci_init; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; +@@ -1141,6 +1143,7 @@ static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->init = virtio_scsi_pci_init_pci; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->props = virtio_scsi_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; +@@ -1197,6 +1200,7 @@ static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->init = vhost_scsi_pci_init_pci; ++ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->props = vhost_scsi_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI; +@@ -1277,6 +1281,7 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->init = virtio_balloon_pci_init; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->props = virtio_balloon_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON; +@@ -1362,6 +1367,7 @@ static void virtio_serial_pci_class_init(ObjectClass *klass, void *data) + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->init = virtio_serial_pci_init; ++ set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->props = virtio_serial_pci_properties; + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE; +@@ -1423,6 +1429,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_VIRTIO_NET; + k->revision = VIRTIO_PCI_ABI_VERSION; + k->class_id = PCI_CLASS_NETWORK_ETHERNET; ++ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->props = virtio_net_properties; + vpciklass->init = virtio_net_pci_init; + } +@@ -1474,6 +1481,7 @@ static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + k->init = virtio_rng_pci_init; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->props = virtio_rng_pci_properties; + + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; +diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c +index cb787c7..bac8421 100644 +--- a/hw/virtio/virtio-rng.c ++++ b/hw/virtio/virtio-rng.c +@@ -207,6 +207,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data) + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + dc->exit = virtio_rng_device_exit; + dc->props = virtio_rng_properties; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + vdc->init = virtio_rng_device_init; + vdc->get_features = get_features; + } +diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c +index 05af0b1..a2ace52 100644 +--- a/hw/watchdog/wdt_i6300esb.c ++++ b/hw/watchdog/wdt_i6300esb.c +@@ -450,6 +450,7 @@ static void i6300esb_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_SYSTEM_OTHER; + dc->reset = i6300esb_reset; + dc->vmsd = &vmstate_i6300esb; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo i6300esb_info = { +diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c +index 6b8e33a..ac88cec 100644 +--- a/hw/watchdog/wdt_ib700.c ++++ b/hw/watchdog/wdt_ib700.c +@@ -131,6 +131,7 @@ static void wdt_ib700_class_init(ObjectClass *klass, void *data) + ic->init = wdt_ib700_init; + dc->reset = wdt_ib700_reset; + dc->vmsd = &vmstate_ib700; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + } + + static const TypeInfo wdt_ib700_info = { +diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c +index b6c6793..bb9d0cd 100644 +--- a/hw/xen/xen_platform.c ++++ b/hw/xen/xen_platform.c +@@ -414,6 +414,7 @@ static void xen_platform_class_init(ObjectClass *klass, void *data) + k->subsystem_vendor_id = PCI_VENDOR_ID_XEN; + k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM; + k->revision = 1; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->desc = "XEN platform pci device"; + dc->reset = platform_reset; + dc->vmsd = &vmstate_xen_platform; +diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c +index c199818..8ba577c 100644 +--- a/hw/xen/xen_pt.c ++++ b/hw/xen/xen_pt.c +@@ -825,6 +825,7 @@ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data) + k->exit = xen_pt_unregister_device; + k->config_read = xen_pt_pci_read_config; + k->config_write = xen_pt_pci_write_config; ++ set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->desc = "Assign an host PCI device with Xen"; + dc->props = xen_pci_passthrough_properties; + }; +-- +1.7.1 + diff --git a/SOURCES/kvm-doc-Drop-ref-to-Bochs-from-no-fd-bootchk-documentati.patch b/SOURCES/kvm-doc-Drop-ref-to-Bochs-from-no-fd-bootchk-documentati.patch new file mode 100644 index 0000000..65767f0 --- /dev/null +++ b/SOURCES/kvm-doc-Drop-ref-to-Bochs-from-no-fd-bootchk-documentati.patch @@ -0,0 +1,56 @@ +From 1af4a2c0eed60017741611d15b22bcdaffc97453 Mon Sep 17 00:00:00 2001 +Message-Id: <1af4a2c0eed60017741611d15b22bcdaffc97453.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:16 +0200 +Subject: [PATCH 06/14] doc: Drop ref to Bochs from -no-fd-bootchk + documentation + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-7-git-send-email-armbru@redhat.com> +Patchwork-id: 54562 +O-Subject: [PATCH 7.0 qemu-kvm 06/10] doc: Drop ref to Bochs from -no-fd-bootchk documentation +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Manual page and qemu-doc on talk about "Bochs BIOS". We use SeaBIOS, +and it implements the feature. Replace by just "BIOS", and drop the +TODO line wondering about the Bochs reference. + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-7-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 4eda32f588086b6cd0ec2be6a7a6c131f8c2b427) +--- + qemu-options.hx | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +Signed-off-by: Michal Novotny +--- + qemu-options.hx | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index 202a2cf..3c60140 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -1268,9 +1268,8 @@ DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk, + STEXI + @item -no-fd-bootchk + @findex -no-fd-bootchk +-Disable boot signature checking for floppy disks in Bochs BIOS. It may ++Disable boot signature checking for floppy disks in BIOS. May + be needed to boot from old floppy disks. +-TODO: check reference to Bochs BIOS. + ETEXI + + DEF("no-acpi", 0, QEMU_OPTION_no_acpi, +-- +1.7.11.7 + diff --git a/SOURCES/kvm-docs-Document-QAPI-union-types.patch b/SOURCES/kvm-docs-Document-QAPI-union-types.patch new file mode 100644 index 0000000..171089f --- /dev/null +++ b/SOURCES/kvm-docs-Document-QAPI-union-types.patch @@ -0,0 +1,125 @@ +From 9ff6403c20232b826766d34cbb66caea8c650bf1 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:10 +0200 +Subject: [PATCH 19/38] docs: Document QAPI union types + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-20-git-send-email-kwolf@redhat.com> +Patchwork-id: 54206 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 19/32] docs: Document QAPI union types +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 51631493e4876081ae27078b50bd95bd4418bf37) + +Signed-off-by: Kevin Wolf +--- + docs/qapi-code-gen.txt | 62 ++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 55 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + docs/qapi-code-gen.txt | 62 ++++++++++++++++++++++++++++++++++++++++++----- + 1 files changed, 55 insertions(+), 7 deletions(-) + +diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt +index cccb11e..f6f8d33 100644 +--- a/docs/qapi-code-gen.txt ++++ b/docs/qapi-code-gen.txt +@@ -34,9 +34,15 @@ OrderedDicts so that ordering is preserved. + There are two basic syntaxes used, type definitions and command definitions. + + The first syntax defines a type and is represented by a dictionary. There are +-two kinds of types that are supported: complex user-defined types, and enums. ++three kinds of user-defined types that are supported: complex types, ++enumeration types and union types. + +-A complex type is a dictionary containing a single key who's value is a ++Generally speaking, types definitions should always use CamelCase for the type ++names. Command names should be all lower case with words separated by a hyphen. ++ ++=== Complex types === ++ ++A complex type is a dictionary containing a single key whose value is a + dictionary. This corresponds to a struct in C or an Object in JSON. An + example of a complex type is: + +@@ -47,13 +53,57 @@ The use of '*' as a prefix to the name means the member is optional. Optional + members should always be added to the end of the dictionary to preserve + backwards compatibility. + +-An enumeration type is a dictionary containing a single key who's value is a ++=== Enumeration types === ++ ++An enumeration type is a dictionary containing a single key whose value is a + list of strings. An example enumeration is: + + { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] } + +-Generally speaking, complex types and enums should always use CamelCase for +-the type names. ++=== Union types === ++ ++Union types are used to let the user choose between several different data ++types. A union type is defined using a dictionary as explained in the ++following paragraphs. ++ ++ ++A simple union type defines a mapping from discriminator values to data types ++like in this example: ++ ++ { 'type': 'FileOptions', 'data': { 'filename': 'str' } } ++ { 'type': 'Qcow2Options', ++ 'data': { 'backing-file': 'str', 'lazy-refcounts': 'bool' } } ++ ++ { 'union': 'BlockdevOptions', ++ 'data': { 'file': 'FileOptions', ++ 'qcow2': 'Qcow2Options' } } ++ ++In the QMP wire format, a simple union is represented by a dictionary that ++contains the 'type' field as a discriminator, and a 'data' field that is of the ++specified data type corresponding to the discriminator value: ++ ++ { "type": "qcow2", "data" : { "backing-file": "/some/place/my-image", ++ "lazy-refcounts": true } } ++ ++ ++A union definition can specify a complex type as its base. In this case, the ++fields of the complex type are included as top-level fields of the union ++dictionary in the QMP wire format. An example definition is: ++ ++ { 'type': 'BlockdevCommonOptions', 'data': { 'readonly': 'bool' } } ++ { 'union': 'BlockdevOptions', ++ 'base': 'BlockdevCommonOptions', ++ 'data': { 'raw': 'RawOptions', ++ 'qcow2': 'Qcow2Options' } } ++ ++And it looks like this on the wire: ++ ++ { "type": "qcow2", ++ "readonly": false, ++ "data" : { "backing-file": "/some/place/my-image", ++ "lazy-refcounts": true } } ++ ++=== Commands === + + Commands are defined by using a list containing three members. The first + member is the command name, the second member is a dictionary containing +@@ -65,8 +115,6 @@ An example command is: + 'data': { 'arg1': 'str', '*arg2': 'str' }, + 'returns': 'str' } + +-Command names should be all lower case with words separated by a hyphen. +- + + == Code generation == + +-- +1.7.1 + diff --git a/SOURCES/kvm-docs-qapi-document-qemu-img-map.patch b/SOURCES/kvm-docs-qapi-document-qemu-img-map.patch new file mode 100644 index 0000000..14ac840 --- /dev/null +++ b/SOURCES/kvm-docs-qapi-document-qemu-img-map.patch @@ -0,0 +1,139 @@ +From f7c79aada82c99552499bc075021128f4a8653a6 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:43 +0200 +Subject: [PATCH 18/81] docs, qapi: document qemu-img map + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-19-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55001 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 18/26] docs, qapi: document qemu-img map +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Eric Blake also requested including the output in qapi-schema.json, +so that it is published through the introspection mechanism. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit facd6e2b5c0217f9d9eeb2ee497dda28009518bd) +--- + qapi-schema.json | 29 +++++++++++++++++++++++++++++ + qemu-img.texi | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 29 ++++++++++++++++++++++++++++ + qemu-img.texi | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+), 0 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index 780c6fe..b779458 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -795,6 +795,35 @@ + { 'enum': 'BlockDeviceIoStatus', 'data': [ 'ok', 'failed', 'nospace' ] } + + ## ++# @BlockDeviceMapEntry: ++# ++# Entry in the metadata map of the device (returned by "qemu-img map") ++# ++# @start: Offset in the image of the first byte described by this entry ++# (in bytes) ++# ++# @length: Length of the range described by this entry (in bytes) ++# ++# @depth: Number of layers (0 = top image, 1 = top image's backing file, etc.) ++# before reaching one for which the range is allocated. The value is ++# in the range 0 to the depth of the image chain - 1. ++# ++# @zero: the sectors in this range read as zeros ++# ++# @data: reading the image will actually read data from a file (in particular, ++# if @offset is present this means that the sectors are not simply ++# preallocated, but contain actual data in raw format) ++# ++# @offset: if present, the image file stores the data for this range in ++# raw format at the given offset. ++# ++# Since 1.7 ++## ++{ 'type': 'BlockDeviceMapEntry', ++ 'data': { 'start': 'int', 'length': 'int', 'depth': 'int', 'zero': 'bool', ++ 'data': 'bool', '*offset': 'int' } } ++ ++## + # @BlockDirtyInfo: + # + # Block dirty bitmap information. +diff --git a/qemu-img.texi b/qemu-img.texi +index 69f1bda..8364fa1 100644 +--- a/qemu-img.texi ++++ b/qemu-img.texi +@@ -213,6 +213,61 @@ To enumerate information about each disk image in the above chain, starting from + qemu-img info --backing-chain snap2.qcow2 + @end example + ++@item map [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} ++ ++Dump the metadata of image @var{filename} and its backing file chain. ++In particular, this commands dumps the allocation state of every sector ++of @var{filename}, together with the topmost file that allocates it in ++the backing file chain. ++ ++Two option formats are possible. The default format (@code{human}) ++only dumps known-nonzero areas of the file. Known-zero parts of the ++file are omitted altogether, and likewise for parts that are not allocated ++throughout the chain. @command{qemu-img} output will identify a file ++from where the data can be read, and the offset in the file. Each line ++will include four fields, the first three of which are hexadecimal ++numbers. For example the first line of: ++@example ++Offset Length Mapped to File ++0 0x20000 0x50000 /tmp/overlay.qcow2 ++0x100000 0x10000 0x95380000 /tmp/backing.qcow2 ++@end example ++@noindent ++means that 0x20000 (131072) bytes starting at offset 0 in the image are ++available in /tmp/overlay.qcow2 (opened in @code{raw} format) starting ++at offset 0x50000 (327680). Data that is compressed, encrypted, or ++otherwise not available in raw format will cause an error if @code{human} ++format is in use. Note that file names can include newlines, thus it is ++not safe to parse this output format in scripts. ++ ++The alternative format @code{json} will return an array of dictionaries ++in JSON format. It will include similar information in ++the @code{start}, @code{length}, @code{offset} fields; ++it will also include other more specific information: ++@itemize @minus ++@item ++whether the sectors contain actual data or not (boolean field @code{data}; ++if false, the sectors are either unallocated or stored as optimized ++all-zero clusters); ++ ++@item ++whether the data is known to read as zero (boolean field @code{zero}); ++ ++@item ++in order to make the output shorter, the target file is expressed as ++a @code{depth}; for example, a depth of 2 refers to the backing file ++of the backing file of @var{filename}. ++@end itemize ++ ++In JSON format, the @code{offset} field is optional; it is absent in ++cases where @code{human} format would omit the entry or exit with an error. ++If @code{data} is false and the @code{offset} field is present, the ++corresponding sectors in the file are not yet in use, but they are ++preallocated. ++ ++For more information, consult @file{include/block/block.h} in QEMU's ++source code. ++ + @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename} + + List, apply, create or delete snapshots in image @var{filename}. +-- +1.7.1 + diff --git a/SOURCES/kvm-don-t-disable-ctrl_mac_addr-feature-for-6.5-machine-.patch b/SOURCES/kvm-don-t-disable-ctrl_mac_addr-feature-for-6.5-machine-.patch new file mode 100644 index 0000000..aaeb05f --- /dev/null +++ b/SOURCES/kvm-don-t-disable-ctrl_mac_addr-feature-for-6.5-machine-.patch @@ -0,0 +1,60 @@ +From d3c44f73a61d44e53612fde282466a3479f33739 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Thu, 7 Nov 2013 08:38:28 +0100 +Subject: [PATCH 25/25] don't disable ctrl_mac_addr feature for 6.5 machine (RHEL only) + +RH-Author: Amos Kong +Message-id: <1383813508-6353-1-git-send-email-akong@redhat.com> +Patchwork-id: 55592 +O-Subject: [RHEL-7.0 qemu-kvm PATCH] don't disable ctrl_mac_addr feature for 6.5 machine (RHEL only) +Bugzilla: 1005039 +RH-Acked-by: Orit Wasserman +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Stefan Hajnoczi + +Bugzilla: 1005039 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6540840 +Test: tested by myself + +ctrl_mac_addr is already supported in qemu-kvm 6.5, +we should not disable this feature for 6.5 machine type. + +Signed-off-by: Amos Kong +--- + hw/i386/pc_piix.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 2d8e79f..8bae4c5 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -784,10 +784,6 @@ static QEMUMachine pc_machine_rhel700 = { + .value = stringify(1),\ + },{\ + .driver = "virtio-net-pci",\ +- .property = "ctrl_mac_addr",\ +- .value = "off",\ +- },{\ +- .driver = "virtio-net-pci",\ + .property = "mq",\ + .value = "off",\ + },{\ +@@ -916,6 +912,10 @@ static QEMUMachine pc_machine_rhel650 = { + .driver = "hda-output",\ + .property = "mixer",\ + .value = "off",\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "ctrl_mac_addr",\ ++ .value = "off",\ + } + + static void pc_init_rhel640(QEMUMachineInitArgs *args) +-- +1.7.1 + diff --git a/SOURCES/kvm-dump-Abstract-dump_init-with-cpu_synchronize_all_states.patch b/SOURCES/kvm-dump-Abstract-dump_init-with-cpu_synchronize_all_states.patch new file mode 100644 index 0000000..63632da --- /dev/null +++ b/SOURCES/kvm-dump-Abstract-dump_init-with-cpu_synchronize_all_states.patch @@ -0,0 +1,51 @@ +From 5f3d2969b85b5e679b6d110d180500914a499993 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:35 +0200 +Subject: dump: Abstract dump_init() with cpu_synchronize_all_states() + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-6-git-send-email-lersek@redhat.com> +Patchwork-id: 53164 +O-Subject: [RHEL-7 qemu-kvm PATCH 05/10] dump: Abstract dump_init() with cpu_synchronize_all_states() +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +From: Andreas Färber + +Instead of calling cpu_synchronize_state() for each CPU, call the +existing cpu_synchronize_all_states() helper. + +Reviewed-by: Luiz Capitulino +Signed-off-by: Andreas Färber +(cherry picked from commit 1b3509ca5bbd8e7d2be92ac42196a3ee2e31cb03) +Signed-off-by: Laszlo Ersek + +diff --git a/dump.c b/dump.c +index c0d3da5..87ca12c 100644 +--- a/dump.c ++++ b/dump.c +@@ -21,6 +21,7 @@ + #include "sysemu/dump.h" + #include "sysemu/sysemu.h" + #include "sysemu/memory_mapping.h" ++#include "sysemu/cpus.h" + #include "qapi/error.h" + #include "qmp-commands.h" + +@@ -731,12 +732,12 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + * If the target architecture is not supported, cpu_get_dump_info() will + * return -1. + * +- * if we use kvm, we should synchronize the register before we get dump ++ * If we use KVM, we should synchronize the registers before we get dump + * info. + */ ++ cpu_synchronize_all_states(); + nr_cpus = 0; + for (env = first_cpu; env != NULL; env = env->next_cpu) { +- cpu_synchronize_state(env); + nr_cpus++; + } + diff --git a/SOURCES/kvm-dump-Move-stubs-into-libqemustub-a.patch b/SOURCES/kvm-dump-Move-stubs-into-libqemustub-a.patch new file mode 100644 index 0000000..3d23ca7 --- /dev/null +++ b/SOURCES/kvm-dump-Move-stubs-into-libqemustub-a.patch @@ -0,0 +1,142 @@ +From fe80e7d53fa6cb0e8f26b76cf6c73acd7010290e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:31 +0200 +Subject: dump: Move stubs into libqemustub.a + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-2-git-send-email-lersek@redhat.com> +Patchwork-id: 53160 +O-Subject: [RHEL-7 qemu-kvm PATCH 01/10] dump: Move stubs into libqemustub.a +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +From: Andreas Färber + +This allows us to drop CONFIG_NO_CORE_DUMP with its indirect dependency +on CONFIG_HAVE_CORE_DUMP. + +Acked-by: Paolo Bonzini +Signed-off-by: Andreas Färber +(cherry picked from commit 88f62c2b1deb466749e340a8a241975c509bd9b6) +Signed-off-by: Laszlo Ersek + +Signed-off-by: Miroslav Rezanina + +diff --git a/Makefile.target b/Makefile.target +index ce4391f..1cafb17 100644 +--- a/Makefile.target ++++ b/Makefile.target +@@ -64,7 +64,6 @@ CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y) + CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y) + CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y) + CONFIG_NO_GET_MEMORY_MAPPING = $(if $(subst n,,$(CONFIG_HAVE_GET_MEMORY_MAPPING)),n,y) +-CONFIG_NO_CORE_DUMP = $(if $(subst n,,$(CONFIG_HAVE_CORE_DUMP)),n,y) + + ######################################################### + # cpu emulator library +@@ -114,7 +113,6 @@ obj-y += memory.o savevm.o cputlb.o + obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o + obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o + obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o +-obj-$(CONFIG_NO_CORE_DUMP) += dump-stub.o + LIBS+=$(libs_softmmu) + + # xen support +diff --git a/dump-stub.c b/dump-stub.c +deleted file mode 100644 +index b3f42cb..0000000 +--- a/dump-stub.c ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* +- * QEMU dump +- * +- * Copyright Fujitsu, Corp. 2011, 2012 +- * +- * Authors: +- * Wen Congyang +- * +- * This work is licensed under the terms of the GNU GPL, version 2 or later. +- * See the COPYING file in the top-level directory. +- * +- */ +- +-#include "qemu-common.h" +-#include "sysemu/dump.h" +-#include "qapi/qmp/qerror.h" +-#include "qmp-commands.h" +- +-/* we need this function in hmp.c */ +-void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, +- int64_t begin, bool has_length, int64_t length, +- Error **errp) +-{ +- error_set(errp, QERR_UNSUPPORTED); +-} +- +-int cpu_get_dump_info(ArchDumpInfo *info) +-{ +- return -1; +-} +- +-ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) +-{ +- return -1; +-} +- +diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs +index 03dff20..9b701b4 100644 +--- a/stubs/Makefile.objs ++++ b/stubs/Makefile.objs +@@ -2,6 +2,7 @@ stub-obj-y += arch-query-cpu-def.o + stub-obj-y += clock-warp.o + stub-obj-y += cpu-get-clock.o + stub-obj-y += cpu-get-icount.o ++stub-obj-y += dump.o + stub-obj-y += fdset-add-fd.o + stub-obj-y += fdset-find-fd.o + stub-obj-y += fdset-get-fd.o +diff --git a/stubs/dump.c b/stubs/dump.c +new file mode 100644 +index 0000000..b3f42cb +--- /dev/null ++++ b/stubs/dump.c +@@ -0,0 +1,36 @@ ++/* ++ * QEMU dump ++ * ++ * Copyright Fujitsu, Corp. 2011, 2012 ++ * ++ * Authors: ++ * Wen Congyang ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu-common.h" ++#include "sysemu/dump.h" ++#include "qapi/qmp/qerror.h" ++#include "qmp-commands.h" ++ ++/* we need this function in hmp.c */ ++void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, ++ int64_t begin, bool has_length, int64_t length, ++ Error **errp) ++{ ++ error_set(errp, QERR_UNSUPPORTED); ++} ++ ++int cpu_get_dump_info(ArchDumpInfo *info) ++{ ++ return -1; ++} ++ ++ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) ++{ ++ return -1; ++} ++ diff --git a/SOURCES/kvm-dump-clamp-guest-provided-mapping-lengths-to-ramblock-sizes.patch b/SOURCES/kvm-dump-clamp-guest-provided-mapping-lengths-to-ramblock-sizes.patch new file mode 100644 index 0000000..f121402 --- /dev/null +++ b/SOURCES/kvm-dump-clamp-guest-provided-mapping-lengths-to-ramblock-sizes.patch @@ -0,0 +1,167 @@ +From 198cca2028659addc6cce1a4fe2f14b7b84d1a22 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:37 +0200 +Subject: dump: clamp guest-provided mapping lengths to ramblock sizes + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-8-git-send-email-lersek@redhat.com> +Patchwork-id: 53169 +O-Subject: [RHEL-7 qemu-kvm PATCH 07/10] dump: clamp guest-provided mapping lengths to ramblock sizes +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +Even a trusted & clean-state guest can map more memory than what it was +given. Since the vmcore contains RAMBlocks, mapping sizes should be +clamped to RAMBlock sizes. Otherwise such oversized mappings can exceed +the entire file size, and ELF parsers might refuse even the valid portion +of the PT_LOAD entry. + +Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582 + +Signed-off-by: Laszlo Ersek +Signed-off-by: Luiz Capitulino +(cherry picked from commit 2cac260768b9d4253737417ea7501cf2950e257f) + +diff --git a/dump.c b/dump.c +index 44a1339..cbfad1c 100644 +--- a/dump.c ++++ b/dump.c +@@ -187,7 +187,8 @@ static int write_elf32_header(DumpState *s) + } + + static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, +- int phdr_index, hwaddr offset) ++ int phdr_index, hwaddr offset, ++ hwaddr filesz) + { + Elf64_Phdr phdr; + int ret; +@@ -197,15 +198,12 @@ static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, + phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian); + phdr.p_offset = cpu_convert_to_target64(offset, endian); + phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian); +- if (offset == -1) { +- /* When the memory is not stored into vmcore, offset will be -1 */ +- phdr.p_filesz = 0; +- } else { +- phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian); +- } ++ phdr.p_filesz = cpu_convert_to_target64(filesz, endian); + phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian); + phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian); + ++ assert(memory_mapping->length >= filesz); ++ + ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s); + if (ret < 0) { + dump_error(s, "dump: failed to write program header table.\n"); +@@ -216,7 +214,8 @@ static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, + } + + static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, +- int phdr_index, hwaddr offset) ++ int phdr_index, hwaddr offset, ++ hwaddr filesz) + { + Elf32_Phdr phdr; + int ret; +@@ -226,15 +225,12 @@ static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, + phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian); + phdr.p_offset = cpu_convert_to_target32(offset, endian); + phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian); +- if (offset == -1) { +- /* When the memory is not stored into vmcore, offset will be -1 */ +- phdr.p_filesz = 0; +- } else { +- phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian); +- } ++ phdr.p_filesz = cpu_convert_to_target32(filesz, endian); + phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian); + phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian); + ++ assert(memory_mapping->length >= filesz); ++ + ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s); + if (ret < 0) { + dump_error(s, "dump: failed to write program header table.\n"); +@@ -422,17 +418,24 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, + return 0; + } + +-/* get the memory's offset in the vmcore */ +-static hwaddr get_offset(hwaddr phys_addr, +- DumpState *s) ++/* get the memory's offset and size in the vmcore */ ++static void get_offset_range(hwaddr phys_addr, ++ ram_addr_t mapping_length, ++ DumpState *s, ++ hwaddr *p_offset, ++ hwaddr *p_filesz) + { + RAMBlock *block; + hwaddr offset = s->memory_offset; + int64_t size_in_block, start; + ++ /* When the memory is not stored into vmcore, offset will be -1 */ ++ *p_offset = -1; ++ *p_filesz = 0; ++ + if (s->has_filter) { + if (phys_addr < s->begin || phys_addr >= s->begin + s->length) { +- return -1; ++ return; + } + } + +@@ -461,18 +464,26 @@ static hwaddr get_offset(hwaddr phys_addr, + } + + if (phys_addr >= start && phys_addr < start + size_in_block) { +- return phys_addr - start + offset; ++ *p_offset = phys_addr - start + offset; ++ ++ /* The offset range mapped from the vmcore file must not spill over ++ * the RAMBlock, clamp it. The rest of the mapping will be ++ * zero-filled in memory at load time; see ++ * . ++ */ ++ *p_filesz = phys_addr + mapping_length <= start + size_in_block ? ++ mapping_length : ++ size_in_block - (phys_addr - start); ++ return; + } + + offset += size_in_block; + } +- +- return -1; + } + + static int write_elf_loads(DumpState *s) + { +- hwaddr offset; ++ hwaddr offset, filesz; + MemoryMapping *memory_mapping; + uint32_t phdr_index = 1; + int ret; +@@ -485,11 +496,15 @@ static int write_elf_loads(DumpState *s) + } + + QTAILQ_FOREACH(memory_mapping, &s->list.head, next) { +- offset = get_offset(memory_mapping->phys_addr, s); ++ get_offset_range(memory_mapping->phys_addr, ++ memory_mapping->length, ++ s, &offset, &filesz); + if (s->dump_info.d_class == ELFCLASS64) { +- ret = write_elf64_load(s, memory_mapping, phdr_index++, offset); ++ ret = write_elf64_load(s, memory_mapping, phdr_index++, offset, ++ filesz); + } else { +- ret = write_elf32_load(s, memory_mapping, phdr_index++, offset); ++ ret = write_elf32_load(s, memory_mapping, phdr_index++, offset, ++ filesz); + } + + if (ret < 0) { diff --git a/SOURCES/kvm-dump-introduce-GuestPhysBlockList.patch b/SOURCES/kvm-dump-introduce-GuestPhysBlockList.patch new file mode 100644 index 0000000..5455783 --- /dev/null +++ b/SOURCES/kvm-dump-introduce-GuestPhysBlockList.patch @@ -0,0 +1,186 @@ +From 0c26814e42d1090b3ad3a20ca97b5a74accee7e9 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:38 +0200 +Subject: dump: introduce GuestPhysBlockList + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-9-git-send-email-lersek@redhat.com> +Patchwork-id: 53166 +O-Subject: [RHEL-7 qemu-kvm PATCH 08/10] dump: introduce GuestPhysBlockList +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +The vmcore must use physical addresses that are visible to the guest, not +addresses that point into linear RAMBlocks. As first step, introduce the +list type into which we'll collect the physical mappings in effect at the +time of the dump. + +Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582 + +Signed-off-by: Laszlo Ersek +Signed-off-by: Luiz Capitulino +(cherry picked from commit 5ee163e8ea2fb6610339f494e039159e08a69066) + +Conflicts: + + dump.c + memory_mapping.c + +The conflicts are due to RHEL-7 not having upstream commit 182735ef ("cpu: +Make first_cpu and next_cpu CPUState"), whose backport I rejected due to +its many dependencies. + +diff --git a/dump.c b/dump.c +index cbfad1c..351233b 100644 +--- a/dump.c ++++ b/dump.c +@@ -59,6 +59,7 @@ static uint64_t cpu_convert_to_target64(uint64_t val, int endian) + } + + typedef struct DumpState { ++ GuestPhysBlockList guest_phys_blocks; + ArchDumpInfo dump_info; + MemoryMappingList list; + uint16_t phdr_num; +@@ -81,6 +82,7 @@ static int dump_cleanup(DumpState *s) + { + int ret = 0; + ++ guest_phys_blocks_free(&s->guest_phys_blocks); + memory_mapping_list_free(&s->list); + if (s->fd != -1) { + close(s->fd); +@@ -732,31 +734,34 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + s->resume = false; + } + ++ /* If we use KVM, we should synchronize the registers before we get dump ++ * info or physmap info. ++ */ ++ cpu_synchronize_all_states(); ++ nr_cpus = 0; ++ for (env = first_cpu; env != NULL; env = env->next_cpu) { ++ nr_cpus++; ++ } ++ + s->errp = errp; + s->fd = fd; + s->has_filter = has_filter; + s->begin = begin; + s->length = length; ++ ++ guest_phys_blocks_init(&s->guest_phys_blocks); ++ /* FILL LIST */ ++ + s->start = get_start_block(s); + if (s->start == -1) { + error_set(errp, QERR_INVALID_PARAMETER, "begin"); + goto cleanup; + } + +- /* +- * get dump info: endian, class and architecture. ++ /* get dump info: endian, class and architecture. + * If the target architecture is not supported, cpu_get_dump_info() will + * return -1. +- * +- * If we use KVM, we should synchronize the registers before we get dump +- * info. + */ +- cpu_synchronize_all_states(); +- nr_cpus = 0; +- for (env = first_cpu; env != NULL; env = env->next_cpu) { +- nr_cpus++; +- } +- + ret = cpu_get_dump_info(&s->dump_info); + if (ret < 0) { + error_set(errp, QERR_UNSUPPORTED); +@@ -831,6 +836,8 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + return 0; + + cleanup: ++ guest_phys_blocks_free(&s->guest_phys_blocks); ++ + if (s->resume) { + vm_start(); + } +@@ -878,7 +885,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, + return; + } + +- s = g_malloc(sizeof(DumpState)); ++ s = g_malloc0(sizeof(DumpState)); + + ret = dump_init(s, fd, paging, has_begin, begin, length, errp); + if (ret < 0) { +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index 6dfb68d..d2d06cd 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -17,6 +17,25 @@ + #include "qemu/queue.h" + #include "qemu/typedefs.h" + ++typedef struct GuestPhysBlock { ++ /* visible to guest, reflects PCI hole, etc */ ++ hwaddr target_start; ++ ++ /* implies size */ ++ hwaddr target_end; ++ ++ /* points into host memory */ ++ uint8_t *host_addr; ++ ++ QTAILQ_ENTRY(GuestPhysBlock) next; ++} GuestPhysBlock; ++ ++/* point-in-time snapshot of guest-visible physical mappings */ ++typedef struct GuestPhysBlockList { ++ unsigned num; ++ QTAILQ_HEAD(GuestPhysBlockHead, GuestPhysBlock) head; ++} GuestPhysBlockList; ++ + /* The physical and virtual address in the memory mapping are contiguous. */ + typedef struct MemoryMapping { + hwaddr phys_addr; +@@ -45,6 +64,9 @@ void memory_mapping_list_free(MemoryMappingList *list); + + void memory_mapping_list_init(MemoryMappingList *list); + ++void guest_phys_blocks_free(GuestPhysBlockList *list); ++void guest_phys_blocks_init(GuestPhysBlockList *list); ++ + void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp); + + /* get guest's memory mapping without do paging(virtual address is 0). */ +diff --git a/memory_mapping.c b/memory_mapping.c +index 5634f81..78a9829 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -165,6 +165,23 @@ void memory_mapping_list_init(MemoryMappingList *list) + QTAILQ_INIT(&list->head); + } + ++void guest_phys_blocks_free(GuestPhysBlockList *list) ++{ ++ GuestPhysBlock *p, *q; ++ ++ QTAILQ_FOREACH_SAFE(p, &list->head, next, q) { ++ QTAILQ_REMOVE(&list->head, p, next); ++ g_free(p); ++ } ++ list->num = 0; ++} ++ ++void guest_phys_blocks_init(GuestPhysBlockList *list) ++{ ++ list->num = 0; ++ QTAILQ_INIT(&list->head); ++} ++ + static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) + { + CPUArchState *env; diff --git a/SOURCES/kvm-dump-populate-guest_phys_blocks.patch b/SOURCES/kvm-dump-populate-guest_phys_blocks.patch new file mode 100644 index 0000000..e0a2885 --- /dev/null +++ b/SOURCES/kvm-dump-populate-guest_phys_blocks.patch @@ -0,0 +1,174 @@ +From f13968b5693d5316f4904cdc32b4327b3974fcc6 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:39 +0200 +Subject: dump: populate guest_phys_blocks + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-10-git-send-email-lersek@redhat.com> +Patchwork-id: 53167 +O-Subject: [RHEL-7 qemu-kvm PATCH 09/10] dump: populate guest_phys_blocks +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +While the machine is paused, in guest_phys_blocks_append() we register a +one-shot MemoryListener, solely for the initial collection of the valid +guest-physical memory ranges that happens at listener registration time. + +For each range that is reported to guest_phys_blocks_region_add(), we +attempt to merge the range with the preceding one. + +Ranges can only be joined if they are contiguous in both guest-physical +address space, and contiguous in host virtual address space. + +The "maximal" ranges that remain in the end constitute the guest-physical +memory map that the dump will be based on. + +Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582 + +Signed-off-by: Laszlo Ersek +Signed-off-by: Luiz Capitulino +(cherry picked from commit c5d7f60f0614250bd925071e25220ce5958f75d0) + +Conflicts: + + memory_mapping.c + +The conflicts are due to RHEL-7 not having: +- upstream commit 182735ef ("cpu: Make first_cpu and next_cpu CPUState"), + whose backport I rejected due to its many dependencies, +- upstream commit 052e87b0 ("memory: make section size a 128-bit + integer"), which seems quite intrusive, and to belong to the middle of a + series. + +diff --git a/dump.c b/dump.c +index 351233b..e6b7a00 100644 +--- a/dump.c ++++ b/dump.c +@@ -750,7 +750,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + s->length = length; + + guest_phys_blocks_init(&s->guest_phys_blocks); +- /* FILL LIST */ ++ guest_phys_blocks_append(&s->guest_phys_blocks); + + s->start = get_start_block(s); + if (s->start == -1) { +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index d2d06cd..b2d7d85 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -66,6 +66,7 @@ void memory_mapping_list_init(MemoryMappingList *list); + + void guest_phys_blocks_free(GuestPhysBlockList *list); + void guest_phys_blocks_init(GuestPhysBlockList *list); ++void guest_phys_blocks_append(GuestPhysBlockList *list); + + void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp); + +diff --git a/memory_mapping.c b/memory_mapping.c +index 78a9829..411aba6 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -11,9 +11,15 @@ + * + */ + ++#include ++ + #include "cpu.h" + #include "exec/cpu-all.h" + #include "sysemu/memory_mapping.h" ++#include "exec/memory.h" ++#include "exec/address-spaces.h" ++ ++//#define DEBUG_GUEST_PHYS_REGION_ADD + + static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, + MemoryMapping *mapping) +@@ -182,6 +188,84 @@ void guest_phys_blocks_init(GuestPhysBlockList *list) + QTAILQ_INIT(&list->head); + } + ++typedef struct GuestPhysListener { ++ GuestPhysBlockList *list; ++ MemoryListener listener; ++} GuestPhysListener; ++ ++static void guest_phys_blocks_region_add(MemoryListener *listener, ++ MemoryRegionSection *section) ++{ ++ GuestPhysListener *g; ++ uint64_t section_size; ++ hwaddr target_start, target_end; ++ uint8_t *host_addr; ++ GuestPhysBlock *predecessor; ++ ++ /* we only care about RAM */ ++ if (!memory_region_is_ram(section->mr)) { ++ return; ++ } ++ ++ g = container_of(listener, GuestPhysListener, listener); ++ section_size = section->size; ++ target_start = section->offset_within_address_space; ++ target_end = target_start + section_size; ++ host_addr = memory_region_get_ram_ptr(section->mr) + ++ section->offset_within_region; ++ predecessor = NULL; ++ ++ /* find continuity in guest physical address space */ ++ if (!QTAILQ_EMPTY(&g->list->head)) { ++ hwaddr predecessor_size; ++ ++ predecessor = QTAILQ_LAST(&g->list->head, GuestPhysBlockHead); ++ predecessor_size = predecessor->target_end - predecessor->target_start; ++ ++ /* the memory API guarantees monotonically increasing traversal */ ++ g_assert(predecessor->target_end <= target_start); ++ ++ /* we want continuity in both guest-physical and host-virtual memory */ ++ if (predecessor->target_end < target_start || ++ predecessor->host_addr + predecessor_size != host_addr) { ++ predecessor = NULL; ++ } ++ } ++ ++ if (predecessor == NULL) { ++ /* isolated mapping, allocate it and add it to the list */ ++ GuestPhysBlock *block = g_malloc0(sizeof *block); ++ ++ block->target_start = target_start; ++ block->target_end = target_end; ++ block->host_addr = host_addr; ++ ++ QTAILQ_INSERT_TAIL(&g->list->head, block, next); ++ ++g->list->num; ++ } else { ++ /* expand predecessor until @target_end; predecessor's start doesn't ++ * change ++ */ ++ predecessor->target_end = target_end; ++ } ++ ++#ifdef DEBUG_GUEST_PHYS_REGION_ADD ++ fprintf(stderr, "%s: target_start=" TARGET_FMT_plx " target_end=" ++ TARGET_FMT_plx ": %s (count: %u)\n", __FUNCTION__, target_start, ++ target_end, predecessor ? "joined" : "added", g->list->num); ++#endif ++} ++ ++void guest_phys_blocks_append(GuestPhysBlockList *list) ++{ ++ GuestPhysListener g = { 0 }; ++ ++ g.list = list; ++ g.listener.region_add = &guest_phys_blocks_region_add; ++ memory_listener_register(&g.listener, &address_space_memory); ++ memory_listener_unregister(&g.listener); ++} ++ + static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) + { + CPUArchState *env; diff --git a/SOURCES/kvm-dump-qmp_dump_guest_memory-use-error_setg_file_open.patch b/SOURCES/kvm-dump-qmp_dump_guest_memory-use-error_setg_file_open.patch new file mode 100644 index 0000000..087be1c --- /dev/null +++ b/SOURCES/kvm-dump-qmp_dump_guest_memory-use-error_setg_file_open.patch @@ -0,0 +1,45 @@ +From a434d825ab57df108ada2531d82e428f0b10e203 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:28 +0100 +Subject: [PATCH 09/29] dump: qmp_dump_guest_memory(): use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-6-git-send-email-lersek@redhat.com> +Patchwork-id: 55195 +O-Subject: [RHEL-7 qemu-kvm PATCH 5/8] dump: qmp_dump_guest_memory(): use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit 7581766b719afd63dcf922ddbf982291f596ed12) +Signed-off-by: Laszlo Ersek +--- + dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + dump.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/dump.c b/dump.c +index 0523ad4..b203a8d 100644 +--- a/dump.c ++++ b/dump.c +@@ -874,7 +874,7 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, + if (strstart(file, "file:", &p)) { + fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR); + if (fd < 0) { +- error_set(errp, QERR_OPEN_FILE_FAILED, p); ++ error_setg_file_open(errp, errno, p); + return; + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-dump-rebase-from-host-private-RAMBlock-offsets-to-guest-physical-addresses.patch b/SOURCES/kvm-dump-rebase-from-host-private-RAMBlock-offsets-to-guest-physical-addresses.patch new file mode 100644 index 0000000..0ca0c95 --- /dev/null +++ b/SOURCES/kvm-dump-rebase-from-host-private-RAMBlock-offsets-to-guest-physical-addresses.patch @@ -0,0 +1,412 @@ +From c67daf48e19c0a73c933d09a4c748cfda8d6d3f2 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:40 +0200 +Subject: dump: rebase from host-private RAMBlock offsets to guest-physical addresses + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-11-git-send-email-lersek@redhat.com> +Patchwork-id: 53168 +O-Subject: [RHEL-7 qemu-kvm PATCH 10/10] dump: rebase from host-private RAMBlock offsets to guest-physical addresses +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +RAMBlock.offset --> GuestPhysBlock.target_start +RAMBlock.offset + RAMBlock.length --> GuestPhysBlock.target_end +RAMBlock.length --> GuestPhysBlock.target_end - + GuestPhysBlock.target_start + +"GuestPhysBlock.host_addr" is only used when writing the dump contents. + +This patch enables "crash" to work with the vmcore by rebasing the vmcore +from the left side of the following diagram to the right side: + +host-private +offset +relative +to ram_addr RAMBlock guest-visible paddrs + 0 +-------------------+.....+-------------------+ 0 + | ^ | | ^ | + | 640 KB | | 640 KB | + | v | | v | + 0x0000a0000 +-------------------+.....+-------------------+ 0x0000a0000 + | ^ | |XXXXXXXXXXXXXXXXXXX| + | 384 KB | |XXXXXXXXXXXXXXXXXXX| + | v | |XXXXXXXXXXXXXXXXXXX| + 0x000100000 +-------------------+.....+-------------------+ 0x000100000 + | ^ | | ^ | + | 3583 MB | | 3583 MB | + | v | | v | + 0x0e0000000 +-------------------+.....+-------------------+ 0x0e0000000 + | ^ |. |XXXXXXXXXXXXXXXXXXX| + | above_4g_mem_size | . |XXXX PCI hole XXXXX| + | v | . |XXXX XXXXX| + ram_size +-------------------+ . |XXXX 512 MB XXXXX| + . .|XXXXXXXXXXXXXXXXXXX| + . +-------------------+ 0x100000000 + . | ^ | + . | above_4g_mem_size | + .| v | + +-------------------+ ram_size + + 512 MB + +Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=981582 + +Signed-off-by: Laszlo Ersek +Signed-off-by: Luiz Capitulino +(cherry picked from commit 56c4bfb3f07f3107894c00281276aea4f5e8834d) + +Conflicts: + + memory_mapping.c + stubs/dump.c + target-s390x/arch_dump.c + +The conflicts are due to RHEL-7 not having +- upstream commit 182735ef ("cpu: Make first_cpu and next_cpu CPUState"), + whose backport I rejected due to its many dependencies, +- upstream commit 9b4f38e1 ("s390: Implement dump-guest-memory support for + target s390x") -- we don't support the s390x target. + +diff --git a/dump.c b/dump.c +index e6b7a00..0523ad4 100644 +--- a/dump.c ++++ b/dump.c +@@ -70,7 +70,7 @@ typedef struct DumpState { + hwaddr memory_offset; + int fd; + +- RAMBlock *block; ++ GuestPhysBlock *next_block; + ram_addr_t start; + bool has_filter; + int64_t begin; +@@ -395,14 +395,14 @@ static int write_data(DumpState *s, void *buf, int length) + } + + /* write the memroy to vmcore. 1 page per I/O. */ +-static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, ++static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start, + int64_t size) + { + int64_t i; + int ret; + + for (i = 0; i < size / TARGET_PAGE_SIZE; i++) { +- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, ++ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE, + TARGET_PAGE_SIZE); + if (ret < 0) { + return ret; +@@ -410,7 +410,7 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start, + } + + if ((size % TARGET_PAGE_SIZE) != 0) { +- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE, ++ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE, + size % TARGET_PAGE_SIZE); + if (ret < 0) { + return ret; +@@ -427,7 +427,7 @@ static void get_offset_range(hwaddr phys_addr, + hwaddr *p_offset, + hwaddr *p_filesz) + { +- RAMBlock *block; ++ GuestPhysBlock *block; + hwaddr offset = s->memory_offset; + int64_t size_in_block, start; + +@@ -441,35 +441,34 @@ static void get_offset_range(hwaddr phys_addr, + } + } + +- QTAILQ_FOREACH(block, &ram_list.blocks, next) { ++ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { + if (s->has_filter) { +- if (block->offset >= s->begin + s->length || +- block->offset + block->length <= s->begin) { ++ if (block->target_start >= s->begin + s->length || ++ block->target_end <= s->begin) { + /* This block is out of the range */ + continue; + } + +- if (s->begin <= block->offset) { +- start = block->offset; ++ if (s->begin <= block->target_start) { ++ start = block->target_start; + } else { + start = s->begin; + } + +- size_in_block = block->length - (start - block->offset); +- if (s->begin + s->length < block->offset + block->length) { +- size_in_block -= block->offset + block->length - +- (s->begin + s->length); ++ size_in_block = block->target_end - start; ++ if (s->begin + s->length < block->target_end) { ++ size_in_block -= block->target_end - (s->begin + s->length); + } + } else { +- start = block->offset; +- size_in_block = block->length; ++ start = block->target_start; ++ size_in_block = block->target_end - block->target_start; + } + + if (phys_addr >= start && phys_addr < start + size_in_block) { + *p_offset = phys_addr - start + offset; + + /* The offset range mapped from the vmcore file must not spill over +- * the RAMBlock, clamp it. The rest of the mapping will be ++ * the GuestPhysBlock, clamp it. The rest of the mapping will be + * zero-filled in memory at load time; see + * . + */ +@@ -617,7 +616,7 @@ static int dump_completed(DumpState *s) + return 0; + } + +-static int get_next_block(DumpState *s, RAMBlock *block) ++static int get_next_block(DumpState *s, GuestPhysBlock *block) + { + while (1) { + block = QTAILQ_NEXT(block, next); +@@ -627,16 +626,16 @@ static int get_next_block(DumpState *s, RAMBlock *block) + } + + s->start = 0; +- s->block = block; ++ s->next_block = block; + if (s->has_filter) { +- if (block->offset >= s->begin + s->length || +- block->offset + block->length <= s->begin) { ++ if (block->target_start >= s->begin + s->length || ++ block->target_end <= s->begin) { + /* This block is out of the range */ + continue; + } + +- if (s->begin > block->offset) { +- s->start = s->begin - block->offset; ++ if (s->begin > block->target_start) { ++ s->start = s->begin - block->target_start; + } + } + +@@ -647,18 +646,18 @@ static int get_next_block(DumpState *s, RAMBlock *block) + /* write all memory to vmcore */ + static int dump_iterate(DumpState *s) + { +- RAMBlock *block; ++ GuestPhysBlock *block; + int64_t size; + int ret; + + while (1) { +- block = s->block; ++ block = s->next_block; + +- size = block->length; ++ size = block->target_end - block->target_start; + if (s->has_filter) { + size -= s->start; +- if (s->begin + s->length < block->offset + block->length) { +- size -= block->offset + block->length - (s->begin + s->length); ++ if (s->begin + s->length < block->target_end) { ++ size -= block->target_end - (s->begin + s->length); + } + } + ret = write_memory(s, block, s->start, size); +@@ -693,23 +692,23 @@ static int create_vmcore(DumpState *s) + + static ram_addr_t get_start_block(DumpState *s) + { +- RAMBlock *block; ++ GuestPhysBlock *block; + + if (!s->has_filter) { +- s->block = QTAILQ_FIRST(&ram_list.blocks); ++ s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head); + return 0; + } + +- QTAILQ_FOREACH(block, &ram_list.blocks, next) { +- if (block->offset >= s->begin + s->length || +- block->offset + block->length <= s->begin) { ++ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { ++ if (block->target_start >= s->begin + s->length || ++ block->target_end <= s->begin) { + /* This block is out of the range */ + continue; + } + +- s->block = block; +- if (s->begin > block->offset) { +- s->start = s->begin - block->offset; ++ s->next_block = block; ++ if (s->begin > block->target_start) { ++ s->start = s->begin - block->target_start; + } else { + s->start = 0; + } +@@ -762,7 +761,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + * If the target architecture is not supported, cpu_get_dump_info() will + * return -1. + */ +- ret = cpu_get_dump_info(&s->dump_info); ++ ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks); + if (ret < 0) { + error_set(errp, QERR_UNSUPPORTED); + goto cleanup; +@@ -778,13 +777,13 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + /* get memory mapping */ + memory_mapping_list_init(&s->list); + if (paging) { +- qemu_get_guest_memory_mapping(&s->list, &err); ++ qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err); + if (err != NULL) { + error_propagate(errp, err); + goto cleanup; + } + } else { +- qemu_get_guest_simple_memory_mapping(&s->list); ++ qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks); + } + + if (s->has_filter) { +diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h +index b8c770f..19fafb2 100644 +--- a/include/sysemu/dump.h ++++ b/include/sysemu/dump.h +@@ -20,7 +20,9 @@ typedef struct ArchDumpInfo { + int d_class; /* ELFCLASS32 or ELFCLASS64 */ + } ArchDumpInfo; + +-int cpu_get_dump_info(ArchDumpInfo *info); ++struct GuestPhysBlockList; /* memory_mapping.h */ ++int cpu_get_dump_info(ArchDumpInfo *info, ++ const struct GuestPhysBlockList *guest_phys_blocks); + ssize_t cpu_get_note_size(int class, int machine, int nr_cpus); + + #endif +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index b2d7d85..a75d59a 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -68,10 +68,13 @@ void guest_phys_blocks_free(GuestPhysBlockList *list); + void guest_phys_blocks_init(GuestPhysBlockList *list); + void guest_phys_blocks_append(GuestPhysBlockList *list); + +-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp); ++void qemu_get_guest_memory_mapping(MemoryMappingList *list, ++ const GuestPhysBlockList *guest_phys_blocks, ++ Error **errp); + + /* get guest's memory mapping without do paging(virtual address is 0). */ +-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list); ++void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list, ++ const GuestPhysBlockList *guest_phys_blocks); + + void memory_mapping_filter(MemoryMappingList *list, int64_t begin, + int64_t length); +diff --git a/memory_mapping.c b/memory_mapping.c +index 411aba6..65082d8 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -279,10 +279,12 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) + return NULL; + } + +-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp) ++void qemu_get_guest_memory_mapping(MemoryMappingList *list, ++ const GuestPhysBlockList *guest_phys_blocks, ++ Error **errp) + { + CPUArchState *env, *first_paging_enabled_cpu; +- RAMBlock *block; ++ GuestPhysBlock *block; + ram_addr_t offset, length; + + first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu); +@@ -302,19 +304,21 @@ void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp) + * If the guest doesn't use paging, the virtual address is equal to physical + * address. + */ +- QTAILQ_FOREACH(block, &ram_list.blocks, next) { +- offset = block->offset; +- length = block->length; ++ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) { ++ offset = block->target_start; ++ length = block->target_end - block->target_start; + create_new_memory_mapping(list, offset, offset, length); + } + } + +-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list) ++void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list, ++ const GuestPhysBlockList *guest_phys_blocks) + { +- RAMBlock *block; ++ GuestPhysBlock *block; + +- QTAILQ_FOREACH(block, &ram_list.blocks, next) { +- create_new_memory_mapping(list, block->offset, 0, block->length); ++ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) { ++ create_new_memory_mapping(list, block->target_start, 0, ++ block->target_end - block->target_start); + } + } + +diff --git a/stubs/dump.c b/stubs/dump.c +index b3f42cb..5749e2c 100644 +--- a/stubs/dump.c ++++ b/stubs/dump.c +@@ -24,7 +24,8 @@ void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin, + error_set(errp, QERR_UNSUPPORTED); + } + +-int cpu_get_dump_info(ArchDumpInfo *info) ++int cpu_get_dump_info(ArchDumpInfo *info, ++ const struct GuestPhysBlockList *guest_phys_blocks) + { + return -1; + } +diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c +index 83898cd..a99ef8c 100644 +--- a/target-i386/arch_dump.c ++++ b/target-i386/arch_dump.c +@@ -15,6 +15,7 @@ + #include "exec/cpu-all.h" + #include "sysemu/dump.h" + #include "elf.h" ++#include "sysemu/memory_mapping.h" + + #ifdef TARGET_X86_64 + typedef struct { +@@ -388,10 +389,11 @@ int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs, + return cpu_write_qemu_note(f, &cpu->env, opaque, 0); + } + +-int cpu_get_dump_info(ArchDumpInfo *info) ++int cpu_get_dump_info(ArchDumpInfo *info, ++ const GuestPhysBlockList *guest_phys_blocks) + { + bool lma = false; +- RAMBlock *block; ++ GuestPhysBlock *block; + + #ifdef TARGET_X86_64 + lma = !!(first_cpu->hflags & HF_LMA_MASK); +@@ -409,8 +411,8 @@ int cpu_get_dump_info(ArchDumpInfo *info) + } else { + info->d_class = ELFCLASS32; + +- QTAILQ_FOREACH(block, &ram_list.blocks, next) { +- if (block->offset + block->length > UINT_MAX) { ++ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) { ++ if (block->target_end > UINT_MAX) { + /* The memory size is greater than 4G */ + info->d_class = ELFCLASS64; + break; diff --git a/SOURCES/kvm-error-add-error_setg_file_open-helper.patch b/SOURCES/kvm-error-add-error_setg_file_open-helper.patch new file mode 100644 index 0000000..ddcb8ab --- /dev/null +++ b/SOURCES/kvm-error-add-error_setg_file_open-helper.patch @@ -0,0 +1,65 @@ +From ab4cb1fa308e6352003b16ef3227e6bcacd2ba08 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:13 +0200 +Subject: [PATCH 06/18] error: add error_setg_file_open() helper + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-6-git-send-email-kraxel@redhat.com> +Patchwork-id: 54853 +O-Subject: [RHEL-7 qemu-kvm PATCH 05/15] error: add error_setg_file_open() helper +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit 54028d7542cffe97c4685994baac66988c4b7db9) +--- + include/qapi/error.h | 5 +++++ + util/error.c | 5 +++++ + 2 files changed, 10 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + include/qapi/error.h | 5 +++++ + util/error.c | 5 +++++ + 2 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/include/qapi/error.h b/include/qapi/error.h +index 5cd2f0c..ffd1cea 100644 +--- a/include/qapi/error.h ++++ b/include/qapi/error.h +@@ -45,6 +45,11 @@ void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char + error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__) + + /** ++ * Helper for open() errors ++ */ ++void error_setg_file_open(Error **errp, int os_errno, const char *filename); ++ ++/** + * Returns true if an indirect pointer to an error is pointing to a valid + * error object. + */ +diff --git a/util/error.c b/util/error.c +index 519f6b6..53b0435 100644 +--- a/util/error.c ++++ b/util/error.c +@@ -71,6 +71,11 @@ void error_set_errno(Error **errp, int os_errno, ErrorClass err_class, + *errp = err; + } + ++void error_setg_file_open(Error **errp, int os_errno, const char *filename) ++{ ++ error_setg_errno(errp, os_errno, "Could not open '%s'", filename); ++} ++ + Error *error_copy(const Error *err) + { + Error *err_new; +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Clean-up-fall-back-when-mem-path-allocation-fai.patch b/SOURCES/kvm-exec-Clean-up-fall-back-when-mem-path-allocation-fai.patch new file mode 100644 index 0000000..64ab4b8 --- /dev/null +++ b/SOURCES/kvm-exec-Clean-up-fall-back-when-mem-path-allocation-fai.patch @@ -0,0 +1,66 @@ +From 897142f67237f772669d48d024e8e7719f6a5a79 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:03 +0200 +Subject: [PATCH 19/29] exec: Clean up fall back when -mem-path allocation fails + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-3-git-send-email-armbru@redhat.com> +Patchwork-id: 54421 +O-Subject: [PATCH 7.0 qemu-kvm 2/8] exec: Clean up fall back when -mem-path allocation fails +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +With -mem-path, qemu_ram_alloc_from_ptr() first tries to allocate +accordingly, but when it fails, it falls back to normal allocation. + +The fall back allocation code used to be effectively identical to the +"-mem-path not given" code, until it started to diverge in commit +432d268. I believe the code still works, but clean it up anyway: drop +the special fall back allocation code, and fall back to the ordinary +"-mem-path not given" code instead. + +Reviewed-by: Paolo Bonzini +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Message-id: 1375276272-15988-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 0628c18267bbe8d44f0faf3e71acf0ae31bea7fd) +--- + exec.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 7 ++----- + 1 files changed, 2 insertions(+), 5 deletions(-) + +diff --git a/exec.c b/exec.c +index 914d066..ef8d311 100644 +--- a/exec.c ++++ b/exec.c +@@ -1063,15 +1063,12 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + if (mem_path) { + #if defined (__linux__) && !defined(TARGET_S390X) + new_block->host = file_ram_alloc(new_block, size, mem_path); +- if (!new_block->host) { +- new_block->host = qemu_anon_ram_alloc(size); +- memory_try_enable_merging(new_block->host, size); +- } + #else + fprintf(stderr, "-mem-path option unsupported\n"); + exit(1); + #endif +- } else { ++ } ++ if (!new_block->host) { + if (kvm_enabled()) { + /* some s390/kvm configurations have special constraints */ + new_block->host = kvm_ram_alloc(size); +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Clean-up-unnecessary-S390-ifdeffery.patch b/SOURCES/kvm-exec-Clean-up-unnecessary-S390-ifdeffery.patch new file mode 100644 index 0000000..2647dca --- /dev/null +++ b/SOURCES/kvm-exec-Clean-up-unnecessary-S390-ifdeffery.patch @@ -0,0 +1,98 @@ +From e4927c8d2802be4adeb25fbdfd538d15211d925e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:07 +0200 +Subject: [PATCH 23/29] exec: Clean up unnecessary S390 ifdeffery + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-7-git-send-email-armbru@redhat.com> +Patchwork-id: 54428 +O-Subject: [PATCH 7.0 qemu-kvm 6/8] exec: Clean up unnecessary S390 ifdeffery +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Another issue missed in commit fdec991 is -mem-path: it needs to be +rejected only for old S390 KVM, not for any S390. Not that I +personally care, but the ifdeffery in qemu_ram_alloc_from_ptr() annoys +me. + +Note that this doesn't actually make -mem-path work, as the kernel +doesn't (yet?) support large pages in the host for KVM guests. Clean +it up anyway. + +Thanks to Christian Borntraeger for pointing out the S390 kernel +limitations. + +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Acked-by: Christian Borntraeger +Message-id: 1375276272-15988-7-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit e1e84ba050538bae24393e40b737078ecad99747) +--- + exec.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 25 +++++++++++++++++++------ + 1 files changed, 19 insertions(+), 6 deletions(-) + +diff --git a/exec.c b/exec.c +index 185155c..a75c200 100644 +--- a/exec.c ++++ b/exec.c +@@ -839,7 +839,7 @@ void qemu_mutex_unlock_ramlist(void) + qemu_mutex_unlock(&ram_list.mutex); + } + +-#if defined(__linux__) && !defined(TARGET_S390X) ++#ifdef __linux__ + + #include + +@@ -942,6 +942,14 @@ static void *file_ram_alloc(RAMBlock *block, + block->fd = fd; + return area; + } ++#else ++static void *file_ram_alloc(RAMBlock *block, ++ ram_addr_t memory, ++ const char *path) ++{ ++ fprintf(stderr, "-mem-path not supported on this host\n"); ++ exit(1); ++} + #endif + + static ram_addr_t find_ram_offset(ram_addr_t size) +@@ -1075,12 +1083,17 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + xen_ram_alloc(new_block->offset, size, mr); + } else { + if (mem_path) { +-#if defined (__linux__) && !defined(TARGET_S390X) ++ if (phys_mem_alloc != qemu_anon_ram_alloc) { ++ /* ++ * file_ram_alloc() needs to allocate just like ++ * phys_mem_alloc, but we haven't bothered to provide ++ * a hook there. ++ */ ++ fprintf(stderr, ++ "-mem-path not supported with this accelerator\n"); ++ exit(1); ++ } + new_block->host = file_ram_alloc(new_block, size, mem_path); +-#else +- fprintf(stderr, "-mem-path option unsupported\n"); +- exit(1); +-#endif + } + if (!new_block->host) { + new_block->host = phys_mem_alloc(size); +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Don-t-abort-when-we-can-t-allocate-guest-memory.patch b/SOURCES/kvm-exec-Don-t-abort-when-we-can-t-allocate-guest-memory.patch new file mode 100644 index 0000000..f5ca77d --- /dev/null +++ b/SOURCES/kvm-exec-Don-t-abort-when-we-can-t-allocate-guest-memory.patch @@ -0,0 +1,117 @@ +From 37bd9dc61bdc4d1a295403360cb0dcab7fbb8936 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:08 +0200 +Subject: [PATCH 24/29] exec: Don't abort when we can't allocate guest memory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-8-git-send-email-armbru@redhat.com> +Patchwork-id: 54425 +O-Subject: [PATCH 7.0 qemu-kvm 7/8] exec: Don't abort when we can't allocate guest memory +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +We abort() on memory allocation failure. abort() is appropriate for +programming errors. Maybe most memory allocation failures are +programming errors, maybe not. But guest memory allocation failure +isn't, and aborting when the user asks for more memory than we can +provide is not nice. exit(1) instead, and do it in just one place, so +the error message is consistent. + +Tested-by: Christian Borntraeger +Signed-off-by: Markus Armbruster +Reviewed-by: Andreas Färber +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Acked-by: Christian Borntraeger +Message-id: 1375276272-15988-8-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 39228250ce6cf67eb1c3799791d271f53c5c6347) +--- + exec.c | 5 +++++ + target-s390x/kvm.c | 6 +----- + util/oslib-posix.c | 4 +--- + util/oslib-win32.c | 5 +---- + 4 files changed, 8 insertions(+), 12 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 5 +++++ + target-s390x/kvm.c | 6 +----- + util/oslib-posix.c | 4 +--- + util/oslib-win32.c | 5 +---- + 4 files changed, 8 insertions(+), 12 deletions(-) + +diff --git a/exec.c b/exec.c +index a75c200..9117a59 100644 +--- a/exec.c ++++ b/exec.c +@@ -1097,6 +1097,11 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + } + if (!new_block->host) { + new_block->host = phys_mem_alloc(size); ++ if (!new_block->host) { ++ fprintf(stderr, "Cannot set up guest memory '%s': %s\n", ++ new_block->mr->name, strerror(errno)); ++ exit(1); ++ } + memory_try_enable_merging(new_block->host, size); + } + } +diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c +index 0b18db4..a106e62 100644 +--- a/target-s390x/kvm.c ++++ b/target-s390x/kvm.c +@@ -331,11 +331,7 @@ static void *legacy_s390_alloc(ram_addr_t size) + mem = mmap((void *) 0x800000000ULL, size, + PROT_EXEC|PROT_READ|PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); +- if (mem == MAP_FAILED) { +- fprintf(stderr, "Allocating RAM failed\n"); +- abort(); +- } +- return mem; ++ return mem == MAP_FAILED ? NULL : mem; + } + + int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index 3dc8b1b..253bc3d 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -112,9 +112,7 @@ void *qemu_anon_ram_alloc(size_t size) + size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; + + if (ptr == MAP_FAILED) { +- fprintf(stderr, "Failed to allocate %zu B: %s\n", +- size, strerror(errno)); +- abort(); ++ return NULL; + } + + ptr += offset; +diff --git a/util/oslib-win32.c b/util/oslib-win32.c +index 961fbf5..983b7a2 100644 +--- a/util/oslib-win32.c ++++ b/util/oslib-win32.c +@@ -65,10 +65,7 @@ void *qemu_anon_ram_alloc(size_t size) + /* FIXME: this is not exactly optimal solution since VirtualAlloc + has 64Kb granularity, but at least it guarantees us that the + memory is page aligned. */ +- if (!size) { +- abort(); +- } +- ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); ++ ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); + trace_qemu_anon_ram_alloc(size, ptr); + return ptr; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Drop-incorrect-dead-S390-code-in-qemu_ram_remap.patch b/SOURCES/kvm-exec-Drop-incorrect-dead-S390-code-in-qemu_ram_remap.patch new file mode 100644 index 0000000..bba8546 --- /dev/null +++ b/SOURCES/kvm-exec-Drop-incorrect-dead-S390-code-in-qemu_ram_remap.patch @@ -0,0 +1,82 @@ +From b65927de7dd0ac9a52fa9b855cd17860c5303e6c Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:06 +0200 +Subject: [PATCH 22/29] exec: Drop incorrect & dead S390 code in qemu_ram_remap() + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-6-git-send-email-armbru@redhat.com> +Patchwork-id: 54426 +O-Subject: [PATCH 7.0 qemu-kvm 5/8] exec: Drop incorrect & dead S390 code in qemu_ram_remap() +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Old S390 KVM wants guest RAM mapped in a peculiar way. Commit 6b02494 +implemented that. + +When qemu_ram_remap() got added in commit cd19cfa, its code carefully +mimicked the allocation code: peculiar way if defined(TARGET_S390X) && +defined(CONFIG_KVM), else normal way. + +For new S390 KVM, we actually want the normal way. Commit fdec991 +changed qemu_ram_alloc_from_ptr() accordingly, but forgot to update +qemu_ram_remap(). If qemu_ram_alloc_from_ptr() maps RAM the normal +way, but qemu_ram_remap() remaps it the peculiar way, remapping +changes protection and flags, which it shouldn't. + +Fortunately, this can't happen, as we never remap on S390. + +Replace the incorrect code with an assertion. + +Thanks to Christian Borntraeger for help with assessing the bug's +(non-)impact. + +Acked-by: Christian Borntraeger +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Message-id: 1375276272-15988-6-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 2eb9fbaab56c6350c7d137428f4bd0bc79168214) +--- + exec.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 13 +++++++------ + 1 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/exec.c b/exec.c +index 42a0005..185155c 100644 +--- a/exec.c ++++ b/exec.c +@@ -1201,15 +1201,16 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) + area = mmap(vaddr, length, PROT_READ | PROT_WRITE, + flags, block->fd, offset); + } else { +-#if defined(TARGET_S390X) && defined(CONFIG_KVM) +- flags |= MAP_SHARED | MAP_ANONYMOUS; +- area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE, +- flags, -1, 0); +-#else ++ /* ++ * Remap needs to match alloc. Accelerators that ++ * set phys_mem_alloc never remap. If they did, ++ * we'd need a remap hook here. ++ */ ++ assert(phys_mem_alloc == qemu_anon_ram_alloc); ++ + flags |= MAP_PRIVATE | MAP_ANONYMOUS; + area = mmap(vaddr, length, PROT_READ | PROT_WRITE, + flags, -1, 0); +-#endif + } + if (area != vaddr) { + fprintf(stderr, "Could not remap addr: " +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Fix-Xen-RAM-allocation-with-unusual-options.patch b/SOURCES/kvm-exec-Fix-Xen-RAM-allocation-with-unusual-options.patch new file mode 100644 index 0000000..f4e2349 --- /dev/null +++ b/SOURCES/kvm-exec-Fix-Xen-RAM-allocation-with-unusual-options.patch @@ -0,0 +1,103 @@ +From 4cdc106eb2e23157acc594b8318a96803df408d0 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:02 +0200 +Subject: [PATCH 18/29] exec: Fix Xen RAM allocation with unusual options + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-2-git-send-email-armbru@redhat.com> +Patchwork-id: 54420 +O-Subject: [PATCH 7.0 qemu-kvm 1/8] exec: Fix Xen RAM allocation with unusual options +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Issues: + +* We try to obey -mem-path even though it can't work with Xen. + +* To implement -machine mem-merge, we call + memory_try_enable_merging(new_block->host, size). But with Xen, + new_block->host remains null. Oops. + +Fix by separating Xen allocation from normal allocation. + +Acked-by: Stefano Stabellini +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Message-id: 1375276272-15988-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit dfeaf2abc73429171ecc5b0b26ac4e5a24c047fc) +--- + exec.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 20 ++++++++++++-------- + 1 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/exec.c b/exec.c +index ee22b9b..914d066 100644 +--- a/exec.c ++++ b/exec.c +@@ -1053,6 +1053,12 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + if (host) { + new_block->host = host; + new_block->flags |= RAM_PREALLOC_MASK; ++ } else if (xen_enabled()) { ++ if (mem_path) { ++ fprintf(stderr, "-mem-path not supported with Xen\n"); ++ exit(1); ++ } ++ xen_ram_alloc(new_block->offset, size, mr); + } else { + if (mem_path) { + #if defined (__linux__) && !defined(TARGET_S390X) +@@ -1066,9 +1072,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + exit(1); + #endif + } else { +- if (xen_enabled()) { +- xen_ram_alloc(new_block->offset, size, mr); +- } else if (kvm_enabled()) { ++ if (kvm_enabled()) { + /* some s390/kvm configurations have special constraints */ + new_block->host = kvm_ram_alloc(size); + } else { +@@ -1146,6 +1150,8 @@ void qemu_ram_free(ram_addr_t addr) + ram_list.version++; + if (block->flags & RAM_PREALLOC_MASK) { + ; ++ } else if (xen_enabled()) { ++ xen_invalidate_map_cache_entry(block->host); + } else if (mem_path) { + #if defined (__linux__) && !defined(TARGET_S390X) + if (block->fd) { +@@ -1158,11 +1164,7 @@ void qemu_ram_free(ram_addr_t addr) + abort(); + #endif + } else { +- if (xen_enabled()) { +- xen_invalidate_map_cache_entry(block->host); +- } else { +- qemu_anon_ram_free(block->host, block->length); +- } ++ qemu_anon_ram_free(block->host, block->length); + } + g_free(block); + break; +@@ -1186,6 +1188,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) + vaddr = block->host + offset; + if (block->flags & RAM_PREALLOC_MASK) { + ; ++ } else if (xen_enabled()) { ++ abort(); + } else { + flags = MAP_FIXED; + munmap(vaddr, length); +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Reduce-ifdeffery-around-mem-path.patch b/SOURCES/kvm-exec-Reduce-ifdeffery-around-mem-path.patch new file mode 100644 index 0000000..189f3e9 --- /dev/null +++ b/SOURCES/kvm-exec-Reduce-ifdeffery-around-mem-path.patch @@ -0,0 +1,119 @@ +From 24775aa5499bad8dea9c067908390c778b4ede6c Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:04 +0200 +Subject: [PATCH 20/29] exec: Reduce ifdeffery around -mem-path + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-4-git-send-email-armbru@redhat.com> +Patchwork-id: 54423 +O-Subject: [PATCH 7.0 qemu-kvm 3/8] exec: Reduce ifdeffery around -mem-path +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Instead of spreading its ifdeffery everywhere, confine it to +qemu_ram_alloc_from_ptr(). Everywhere else, simply test block->fd, +which is non-negative exactly when block uses -mem-path. + +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Message-id: 1375276272-15988-4-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 3435f39513a104294b5e3bbf3612047028d25cfc) +--- + exec.c | 37 ++++++++++--------------------------- + include/exec/cpu-all.h | 2 -- + 2 files changed, 10 insertions(+), 29 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 37 ++++++++++--------------------------- + include/exec/cpu-all.h | 2 -- + 2 files changed, 10 insertions(+), 29 deletions(-) + +diff --git a/exec.c b/exec.c +index ef8d311..32ed61c 100644 +--- a/exec.c ++++ b/exec.c +@@ -1045,6 +1045,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + + size = TARGET_PAGE_ALIGN(size); + new_block = g_malloc0(sizeof(*new_block)); ++ new_block->fd = -1; + + /* This assumes the iothread lock is taken here too. */ + qemu_mutex_lock_ramlist(); +@@ -1149,17 +1150,9 @@ void qemu_ram_free(ram_addr_t addr) + ; + } else if (xen_enabled()) { + xen_invalidate_map_cache_entry(block->host); +- } else if (mem_path) { +-#if defined (__linux__) && !defined(TARGET_S390X) +- if (block->fd) { +- munmap(block->host, block->length); +- close(block->fd); +- } else { +- qemu_anon_ram_free(block->host, block->length); +- } +-#else +- abort(); +-#endif ++ } else if (block->fd >= 0) { ++ munmap(block->host, block->length); ++ close(block->fd); + } else { + qemu_anon_ram_free(block->host, block->length); + } +@@ -1190,25 +1183,15 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) + } else { + flags = MAP_FIXED; + munmap(vaddr, length); +- if (mem_path) { +-#if defined(__linux__) && !defined(TARGET_S390X) +- if (block->fd) { ++ if (block->fd >= 0) { + #ifdef MAP_POPULATE +- flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : +- MAP_PRIVATE; ++ flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED : ++ MAP_PRIVATE; + #else +- flags |= MAP_PRIVATE; +-#endif +- area = mmap(vaddr, length, PROT_READ | PROT_WRITE, +- flags, block->fd, offset); +- } else { +- flags |= MAP_PRIVATE | MAP_ANONYMOUS; +- area = mmap(vaddr, length, PROT_READ | PROT_WRITE, +- flags, -1, 0); +- } +-#else +- abort(); ++ flags |= MAP_PRIVATE; + #endif ++ area = mmap(vaddr, length, PROT_READ | PROT_WRITE, ++ flags, block->fd, offset); + } else { + #if defined(TARGET_S390X) && defined(CONFIG_KVM) + flags |= MAP_SHARED | MAP_ANONYMOUS; +diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h +index e9c3717..c369b25 100644 +--- a/include/exec/cpu-all.h ++++ b/include/exec/cpu-all.h +@@ -476,9 +476,7 @@ typedef struct RAMBlock { + * Writes must take both locks. + */ + QTAILQ_ENTRY(RAMBlock) next; +-#if defined(__linux__) && !defined(TARGET_S390X) + int fd; +-#endif + } RAMBlock; + + typedef struct RAMList { +-- +1.7.1 + diff --git a/SOURCES/kvm-exec-Simplify-the-guest-physical-memory-allocation-h.patch b/SOURCES/kvm-exec-Simplify-the-guest-physical-memory-allocation-h.patch new file mode 100644 index 0000000..4dd16c7 --- /dev/null +++ b/SOURCES/kvm-exec-Simplify-the-guest-physical-memory-allocation-h.patch @@ -0,0 +1,184 @@ +From b84b9552e5d474f237824a33e7211dfac8d2de60 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:05 +0200 +Subject: [PATCH 21/29] exec: Simplify the guest physical memory allocation hook + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-5-git-send-email-armbru@redhat.com> +Patchwork-id: 54424 +O-Subject: [PATCH 7.0 qemu-kvm 4/8] exec: Simplify the guest physical memory allocation hook +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Make it a generic hook rather than a KVM hook. Less code and +ifdeffery. + +Since the only user of the hook is old S390 KVM, there's hope we can +get rid of it some day. + +Acked-by: Christian Borntraeger +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Message-id: 1375276272-15988-5-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 91138037cb341a04a66e4c43b6cb31d5d8a43a73) + +Conflicts: + exec.c + +Trivial conflict because we don't have upstream commits acc9d80 and +058bc4b. +--- + exec.c | 20 ++++++++++++++------ + include/exec/exec-all.h | 2 ++ + include/sysemu/kvm.h | 5 ----- + kvm-all.c | 13 ------------- + target-s390x/kvm.c | 17 ++++++----------- + 5 files changed, 22 insertions(+), 35 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + exec.c | 20 ++++++++++++++------ + include/exec/exec-all.h | 2 ++ + include/sysemu/kvm.h | 5 ----- + kvm-all.c | 13 ------------- + target-s390x/kvm.c | 17 ++++++----------- + 5 files changed, 22 insertions(+), 35 deletions(-) + +diff --git a/exec.c b/exec.c +index 32ed61c..42a0005 100644 +--- a/exec.c ++++ b/exec.c +@@ -679,6 +679,19 @@ typedef struct subpage_t { + static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, + uint16_t section); + static subpage_t *subpage_init(hwaddr base); ++ ++static void *(*phys_mem_alloc)(ram_addr_t size) = qemu_anon_ram_alloc; ++ ++/* ++ * Set a custom physical guest memory alloator. ++ * Accelerators with unusual needs may need this. Hopefully, we can ++ * get rid of it eventually. ++ */ ++void phys_mem_set_alloc(void *(*alloc)(ram_addr_t)) ++{ ++ phys_mem_alloc = alloc; ++} ++ + static void destroy_page_desc(uint16_t section_index) + { + MemoryRegionSection *section = &phys_sections[section_index]; +@@ -1070,12 +1083,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + #endif + } + if (!new_block->host) { +- if (kvm_enabled()) { +- /* some s390/kvm configurations have special constraints */ +- new_block->host = kvm_ram_alloc(size); +- } else { +- new_block->host = qemu_anon_ram_alloc(size); +- } ++ new_block->host = phys_mem_alloc(size); + memory_try_enable_merging(new_block->host, size); + } + } +diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h +index 6362074..993c655 100644 +--- a/include/exec/exec-all.h ++++ b/include/exec/exec-all.h +@@ -366,6 +366,8 @@ bool is_tcg_gen_code(uintptr_t pc_ptr); + + #if !defined(CONFIG_USER_ONLY) + ++void phys_mem_set_alloc(void *(*alloc)(ram_addr_t)); ++ + struct MemoryRegion *iotlb_to_region(hwaddr index); + uint64_t io_mem_read(struct MemoryRegion *mr, hwaddr addr, + unsigned size); +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 08284ef..7fc3844 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -141,11 +141,6 @@ int kvm_init_vcpu(CPUState *cpu); + #ifdef NEED_CPU_H + int kvm_cpu_exec(CPUArchState *env); + +-#if !defined(CONFIG_USER_ONLY) +-void *kvm_ram_alloc(ram_addr_t size); +-void *kvm_arch_ram_alloc(ram_addr_t size); +-#endif +- + void kvm_setup_guest_memory(void *start, size_t size); + void kvm_flush_coalesced_mmio_buffer(void); + +diff --git a/kvm-all.c b/kvm-all.c +index 545b470..d0a7c21 100644 +--- a/kvm-all.c ++++ b/kvm-all.c +@@ -1794,19 +1794,6 @@ int kvm_has_intx_set_mask(void) + return kvm_state->intx_set_mask; + } + +-void *kvm_ram_alloc(ram_addr_t size) +-{ +-#ifdef TARGET_S390X +- void *mem; +- +- mem = kvm_arch_ram_alloc(size); +- if (mem) { +- return mem; +- } +-#endif +- return qemu_anon_ram_alloc(size); +-} +- + void kvm_setup_guest_memory(void *start, size_t size) + { + #ifdef CONFIG_VALGRIND_H +diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c +index 862fb12..0b18db4 100644 +--- a/target-s390x/kvm.c ++++ b/target-s390x/kvm.c +@@ -92,9 +92,15 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + + static int cap_sync_regs; + ++static void *legacy_s390_alloc(ram_addr_t size); ++ + int kvm_arch_init(KVMState *s) + { + cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); ++ if (!kvm_check_extension(s, KVM_CAP_S390_GMAP) ++ || !kvm_check_extension(s, KVM_CAP_S390_COW)) { ++ phys_mem_set_alloc(legacy_s390_alloc); ++ } + return 0; + } + +@@ -332,17 +338,6 @@ static void *legacy_s390_alloc(ram_addr_t size) + return mem; + } + +-void *kvm_arch_ram_alloc(ram_addr_t size) +-{ +- /* Can we use the standard allocation ? */ +- if (kvm_check_extension(kvm_state, KVM_CAP_S390_GMAP) && +- kvm_check_extension(kvm_state, KVM_CAP_S390_COW)) { +- return NULL; +- } else { +- return legacy_s390_alloc(size); +- } +-} +- + int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) + { + S390CPU *cpu = S390_CPU(cs); +-- +1.7.1 + diff --git a/SOURCES/kvm-fix-steal-time-MSR-vmsd-callback-to-proper-opaque-ty.patch b/SOURCES/kvm-fix-steal-time-MSR-vmsd-callback-to-proper-opaque-ty.patch new file mode 100644 index 0000000..5bb17d2 --- /dev/null +++ b/SOURCES/kvm-fix-steal-time-MSR-vmsd-callback-to-proper-opaque-ty.patch @@ -0,0 +1,55 @@ +From 1cec05857c5aaa0eebe75e7c2e6c6116fb9759cd Mon Sep 17 00:00:00 2001 +From: Marcelo Tosatti +Date: Mon, 23 Sep 2013 20:00:13 +0200 +Subject: [PATCH 29/29] fix steal time MSR vmsd callback to proper opaque type + +RH-Author: Marcelo Tosatti +Message-id: <20130923200013.GA20765@amt.cnet> +Patchwork-id: 54498 +O-Subject: [RHEL7 qemu-kvm PATCH] fix steal time MSR vmsd callback to proper opaque type +Bugzilla: 903889 +RH-Acked-by: Andrew Jones +RH-Acked-by: Gleb Natapov +RH-Acked-by: Paolo Bonzini + +BZ: 903889 + +commit 0e5035776df31380a44a1a851850d110b551ecb6 of uq/master branch of qemu-kvm.git repo + +Convert steal time MSR vmsd callback pointer to proper X86CPU type. + +Signed-off-by: Marcelo Tosatti +Signed-off-by: Paolo Bonzini +Signed-off-by: Miroslav Rezanina +--- + target-i386/machine.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 3659db9..ecf1617 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -294,9 +294,9 @@ static bool pv_eoi_msr_needed(void *opaque) + + static bool steal_time_msr_needed(void *opaque) + { +- CPUX86State *cpu = opaque; ++ X86CPU *cpu = opaque; + +- return cpu->steal_time_msr != 0; ++ return cpu->env.steal_time_msr != 0; + } + + static const VMStateDescription vmstate_steal_time_msr = { +@@ -305,7 +305,7 @@ static const VMStateDescription vmstate_steal_time_msr = { + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { +- VMSTATE_UINT64(steal_time_msr, CPUX86State), ++ VMSTATE_UINT64(env.steal_time_msr, X86CPU), + VMSTATE_END_OF_LIST() + } + }; +-- +1.7.1 + diff --git a/SOURCES/kvm-fw_cfg-add-API-to-find-FW-cfg-object.patch b/SOURCES/kvm-fw_cfg-add-API-to-find-FW-cfg-object.patch new file mode 100644 index 0000000..77955c2 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-add-API-to-find-FW-cfg-object.patch @@ -0,0 +1,113 @@ +From b33784c26d96c3c020f4b0245f77731af3f88b8e Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:29 +0100 +Subject: [PATCH 70/81] fw_cfg: add API to find FW cfg object + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-2-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55546 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 1/9] fw_cfg: add API to find FW cfg object +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: "Michael S. Tsirkin" + +Remove some code duplication by adding a +function to look up the fw cfg file. +This way, we don't need to duplicate same strings everywhere. +Use by both fw cfg and pvpanic device. + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 600c60b76d0682f6c39d19bfff79da9321e8cf86) +Signed-off-by: Marcel Apfelbaum +--- + hw/misc/pvpanic.c | 2 +- + hw/nvram/fw_cfg.c | 15 ++++++++++++--- + include/hw/nvram/fw_cfg.h | 2 ++ + 3 files changed, 15 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/pvpanic.c | 2 +- + hw/nvram/fw_cfg.c | 15 ++++++++++++--- + include/hw/nvram/fw_cfg.h | 2 ++ + 3 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index 439d636..d17c3c9 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -96,7 +96,7 @@ static int pvpanic_isa_initfn(ISADevice *dev) + isa_register_ioport(dev, &s->io, s->ioport); + + if (!port_configured) { +- fw_cfg = object_resolve_path("/machine/fw_cfg", NULL); ++ fw_cfg = fw_cfg_find(); + if (fw_cfg) { + fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", + g_memdup(&s->ioport, sizeof(s->ioport)), +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 3fa1488..064344d 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -32,6 +32,9 @@ + + #define FW_CFG_SIZE 2 + #define FW_CFG_DATA_SIZE 1 ++#define TYPE_FW_CFG "fw_cfg" ++#define FW_CFG_NAME "fw_cfg" ++#define FW_CFG_PATH "/machine/" FW_CFG_NAME + + typedef struct FWCfgEntry { + uint32_t len; +@@ -493,8 +496,8 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, + + s = DO_UPCAST(FWCfgState, busdev.qdev, dev); + +- if (!object_resolve_path("/machine/fw_cfg", NULL)) { +- object_property_add_child(qdev_get_machine(), "fw_cfg", OBJECT(s), ++ if (!object_resolve_path(FW_CFG_PATH, NULL)) { ++ object_property_add_child(qdev_get_machine(), FW_CFG_NAME, OBJECT(s), + NULL); + } + +@@ -553,6 +556,12 @@ static Property fw_cfg_properties[] = { + DEFINE_PROP_END_OF_LIST(), + }; + ++FWCfgState *fw_cfg_find(void) ++{ ++ return OBJECT_CHECK(FWCfgState, object_resolve_path(FW_CFG_PATH, NULL), ++ TYPE_FW_CFG); ++} ++ + static void fw_cfg_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); +@@ -565,7 +574,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) + } + + static const TypeInfo fw_cfg_info = { +- .name = "fw_cfg", ++ .name = TYPE_FW_CFG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(FWCfgState), + .class_init = fw_cfg_class_init, +diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h +index 3e4a334..48a8aa4 100644 +--- a/include/hw/nvram/fw_cfg.h ++++ b/include/hw/nvram/fw_cfg.h +@@ -73,6 +73,8 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, + FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, + hwaddr crl_addr, hwaddr data_addr); + ++FWCfgState *fw_cfg_find(void); ++ + #endif /* NO_QEMU_PROTOS */ + + #endif +-- +1.7.1 + diff --git a/SOURCES/kvm-gdbstub-do-not-restart-crashed-guest.patch b/SOURCES/kvm-gdbstub-do-not-restart-crashed-guest.patch new file mode 100644 index 0000000..1c5309d --- /dev/null +++ b/SOURCES/kvm-gdbstub-do-not-restart-crashed-guest.patch @@ -0,0 +1,53 @@ +From c1da75fb13fdb39be174be97ce3428356f10d320 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:34 +0100 +Subject: [PATCH 75/81] gdbstub: do not restart crashed guest + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-7-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55551 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 6/9] gdbstub: do not restart crashed guest +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: Paolo Bonzini + +If a guest has crashed with an internal error or similar, detaching +gdb (or any other debugger action) should not restart it. + +Cc: Jan Kiszka +Signed-off-by: Paolo Bonzini +Reviewed-by: Laszlo Ersek +Message-id: 1369912840-18577-1-git-send-email-pbonzini@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 87f25c12bfeaaa0c41fb857713bbc7e8a9b757dc) +Signed-off-by: Marcel Apfelbaum +--- + gdbstub.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + gdbstub.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/gdbstub.c b/gdbstub.c +index e80e1d3..90e54cb 100644 +--- a/gdbstub.c ++++ b/gdbstub.c +@@ -371,7 +371,9 @@ static inline void gdb_continue(GDBState *s) + #ifdef CONFIG_USER_ONLY + s->running_state = 1; + #else +- vm_start(); ++ if (runstate_check(RUN_STATE_DEBUG)) { ++ vm_start(); ++ } + #endif + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-gdbstub-fix-for-commit-87f25c12bfeaaa0c41fb857713bbc.patch b/SOURCES/kvm-gdbstub-fix-for-commit-87f25c12bfeaaa0c41fb857713bbc.patch new file mode 100644 index 0000000..3d87f19 --- /dev/null +++ b/SOURCES/kvm-gdbstub-fix-for-commit-87f25c12bfeaaa0c41fb857713bbc.patch @@ -0,0 +1,54 @@ +From 8ca5737b301aa2fe62dcb749c9c559195b534dd3 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:35 +0100 +Subject: [PATCH 76/81] gdbstub: fix for commit 87f25c12bfeaaa0c41fb857713bbc7e8a9b757dc + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-8-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55552 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 7/9] gdbstub: fix for commit 87f25c12bfeaaa0c41fb857713bbc7e8a9b757dc +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: Paolo Bonzini + +This commit used the wrong check to prevent an assertion failure. +After this commit, you need to start a guest in the monitor, you +cannot use anymore the "c" command in the debugger. This is +undesirable. The commit's aim was to prevent a restart +after a KVM internal error or something like that; use +runstate_needs_reset() for that. + +Signed-off-by: Paolo Bonzini +Reviewed-by: Luiz Capitulino +Message-id: 1370272015-9659-2-git-send-email-pbonzini@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 26ac7a31fbf5522d2ca3f0e2e5b5c8e915701f66) +Signed-off-by: Marcel Apfelbaum +--- + gdbstub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + gdbstub.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/gdbstub.c b/gdbstub.c +index 90e54cb..e8541f3 100644 +--- a/gdbstub.c ++++ b/gdbstub.c +@@ -371,7 +371,7 @@ static inline void gdb_continue(GDBState *s) + #ifdef CONFIG_USER_ONLY + s->running_state = 1; + #else +- if (runstate_check(RUN_STATE_DEBUG)) { ++ if (!runstate_needs_reset()) { + vm_start(); + } + #endif +-- +1.7.1 + diff --git a/SOURCES/kvm-gluster-Abort-on-AIO-completion-failure.patch b/SOURCES/kvm-gluster-Abort-on-AIO-completion-failure.patch new file mode 100644 index 0000000..2b202a8 --- /dev/null +++ b/SOURCES/kvm-gluster-Abort-on-AIO-completion-failure.patch @@ -0,0 +1,73 @@ +From ecfbec2139f06a75a03c510e24f265a869684edb Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Thu, 12 Sep 2013 07:39:35 +0200 +Subject: [PATCH 15/29] gluster: Abort on AIO completion failure + +RH-Author: Asias He +Message-id: <1378971575-22416-5-git-send-email-asias@redhat.com> +Patchwork-id: 54324 +O-Subject: [RHEL7.0 qemu-kvm PATCH 4/4] gluster: Abort on AIO completion failure +Bugzilla: 1007226 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng + +From: Bharata B Rao + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1004733 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6275752 + +Currently if gluster AIO callback thread fails to notify the QEMU thread about +AIO completion, we try graceful recovery by marking the disk drive as +inaccessible. This error recovery code is race-prone as found by Asias and +Stefan. However as found out by Paolo, this kind of error is impossible and +hence simplify the code that handles this error recovery. + +Signed-off-by: Bharata B Rao +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 9faa574f7d07109e2256c0b4b63e8711d650f2d8) + +Conflicts: + block/gluster.c +--- + block/gluster.c | 17 ++--------------- + 1 file changed, 2 insertions(+), 15 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 17 ++--------------- + 1 files changed, 2 insertions(+), 15 deletions(-) + +diff --git a/block/gluster.c b/block/gluster.c +index 7b10e9c..90a51ca 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -436,22 +436,9 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) + /* + * Gluster AIO callback thread failed to notify the waiting + * QEMU thread about IO completion. +- * +- * Complete this IO request and make the disk inaccessible for +- * subsequent reads and writes. + */ +- error_report("Gluster failed to notify QEMU about IO completion"); +- +- qemu_mutex_lock_iothread(); /* We are in gluster thread context */ +- acb->common.cb(acb->common.opaque, -EIO); +- qemu_aio_release(acb); +- s->qemu_aio_count--; +- close(s->fds[GLUSTER_FD_READ]); +- close(s->fds[GLUSTER_FD_WRITE]); +- qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, +- NULL); +- bs->drv = NULL; /* Make the disk inaccessible */ +- qemu_mutex_unlock_iothread(); ++ error_report("Gluster AIO completion failed: %s", strerror(errno)); ++ abort(); + } + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-gluster-Add-image-resize-support.patch b/SOURCES/kvm-gluster-Add-image-resize-support.patch new file mode 100644 index 0000000..0055723 --- /dev/null +++ b/SOURCES/kvm-gluster-Add-image-resize-support.patch @@ -0,0 +1,96 @@ +From 4f7481a9815ec6b879db9cb20be7dcc419274e11 Mon Sep 17 00:00:00 2001 +From: Asias He +Date: Thu, 12 Sep 2013 07:39:32 +0200 +Subject: [PATCH 12/29] gluster: Add image resize support + +RH-Author: Asias He +Message-id: <1378971575-22416-2-git-send-email-asias@redhat.com> +Patchwork-id: 54323 +O-Subject: [RHEL7.0 qemu-kvm PATCH 1/4] gluster: Add image resize support +Bugzilla: 1007226 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng + +From: Paolo Bonzini + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1005052 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6275752 + +Implement .bdrv_truncate in GlusterFS block driver so that GlusterFS backend +can support image resizing. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Bharata B Rao +Tested-by: Bharata B Rao +Acked-by: Stefan Hajnoczi +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 42ec24e2851674e0899f71933e0d7d9125f31d76) +--- + block/gluster.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 17 +++++++++++++++++ + 1 files changed, 17 insertions(+), 0 deletions(-) + +diff --git a/block/gluster.c b/block/gluster.c +index 61424bc..7b10e9c 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -493,6 +493,19 @@ out: + return NULL; + } + ++static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset) ++{ ++ int ret; ++ BDRVGlusterState *s = bs->opaque; ++ ++ ret = glfs_ftruncate(s->fd, offset); ++ if (ret < 0) { ++ return -errno; ++ } ++ ++ return 0; ++} ++ + static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +@@ -598,6 +611,7 @@ static BlockDriver bdrv_gluster = { + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, ++ .bdrv_truncate = qemu_gluster_truncate, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, +@@ -614,6 +628,7 @@ static BlockDriver bdrv_gluster_tcp = { + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, ++ .bdrv_truncate = qemu_gluster_truncate, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, +@@ -630,6 +645,7 @@ static BlockDriver bdrv_gluster_unix = { + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, ++ .bdrv_truncate = qemu_gluster_truncate, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, +@@ -646,6 +662,7 @@ static BlockDriver bdrv_gluster_rdma = { + .bdrv_create = qemu_gluster_create, + .bdrv_getlength = qemu_gluster_getlength, + .bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size, ++ .bdrv_truncate = qemu_gluster_truncate, + .bdrv_aio_readv = qemu_gluster_aio_readv, + .bdrv_aio_writev = qemu_gluster_aio_writev, + .bdrv_aio_flush = qemu_gluster_aio_flush, +-- +1.7.1 + diff --git a/SOURCES/kvm-hda-codec-make-mixemu-selectable-at-runtime.patch b/SOURCES/kvm-hda-codec-make-mixemu-selectable-at-runtime.patch new file mode 100644 index 0000000..b5f7ada --- /dev/null +++ b/SOURCES/kvm-hda-codec-make-mixemu-selectable-at-runtime.patch @@ -0,0 +1,438 @@ +From 76e63c2bd20deda91bf99de161deb85b5229bf7e Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Tue, 15 Oct 2013 17:10:59 +0200 +Subject: [PATCH 22/25] hda-codec: make mixemu selectable at runtime + +RH-Author: Bandan Das +Message-id: <1381857067-9399-3-git-send-email-bsd@redhat.com> +Patchwork-id: 54950 +O-Subject: [PATCH RHEL-7 qemu-kvm v3 2/5] hda-codec: make mixemu selectable at runtime +Bugzilla: 954195 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster + +Define PARAM so that we have two versions of the "desc_codec +and family" structs. Add a property called "mixer" whose default +value depends on whether CONFIG_MIXEMU is defined or not which +will help us call the appropriate instance init functions. + +Signed-off-by: Bandan Das +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 2690e61e8e313461428334586ed9dbf56531dae9) +--- + hw/audio/hda-codec-common.h | 117 +++++++++++++++++++++++--------------------- + hw/audio/hda-codec.c | 64 ++++++++++++++++++++++-- + 2 files changed, 122 insertions(+), 59 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/audio/hda-codec-common.h | 117 +++++++++++++++++++++++-------------------- + hw/audio/hda-codec.c | 64 ++++++++++++++++++++++-- + 2 files changed, 122 insertions(+), 59 deletions(-) + +diff --git a/hw/audio/hda-codec-common.h b/hw/audio/hda-codec-common.h +index 2f7e95f..b4fdb51 100644 +--- a/hw/audio/hda-codec-common.h ++++ b/hw/audio/hda-codec-common.h +@@ -24,7 +24,7 @@ + * HDA codec descriptions + */ + +-#ifdef CONFIG_MIXEMU ++#ifdef HDA_MIXER + #define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12) + #define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22) + #define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32) +@@ -42,7 +42,7 @@ + + + /* common: audio output widget */ +-static const desc_param common_params_audio_dac[] = { ++static const desc_param glue(common_params_audio_dac_, PARAM)[] = { + { + .id = AC_PAR_AUDIO_WIDGET_CAP, + .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) | +@@ -66,7 +66,7 @@ static const desc_param common_params_audio_dac[] = { + }; + + /* common: audio input widget */ +-static const desc_param common_params_audio_adc[] = { ++static const desc_param glue(common_params_audio_adc_, PARAM)[] = { + { + .id = AC_PAR_AUDIO_WIDGET_CAP, + .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) | +@@ -94,7 +94,7 @@ static const desc_param common_params_audio_adc[] = { + }; + + /* common: pin widget (line-out) */ +-static const desc_param common_params_audio_lineout[] = { ++static const desc_param glue(common_params_audio_lineout_, PARAM)[] = { + { + .id = AC_PAR_AUDIO_WIDGET_CAP, + .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | +@@ -116,7 +116,7 @@ static const desc_param common_params_audio_lineout[] = { + }; + + /* common: pin widget (line-in) */ +-static const desc_param common_params_audio_linein[] = { ++static const desc_param glue(common_params_audio_linein_, PARAM)[] = { + { + .id = AC_PAR_AUDIO_WIDGET_CAP, + .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | +@@ -134,7 +134,7 @@ static const desc_param common_params_audio_linein[] = { + }; + + /* output: root node */ +-static const desc_param output_params_root[] = { ++static const desc_param glue(output_params_root_, PARAM)[] = { + { + .id = AC_PAR_VENDOR_ID, + .val = QEMU_HDA_ID_OUTPUT, +@@ -151,7 +151,7 @@ static const desc_param output_params_root[] = { + }; + + /* output: audio function */ +-static const desc_param output_params_audio_func[] = { ++static const desc_param glue(output_params_audio_func_, PARAM)[] = { + { + .id = AC_PAR_FUNCTION_TYPE, + .val = AC_GRP_AUDIO_FUNCTION, +@@ -186,28 +186,28 @@ static const desc_param output_params_audio_func[] = { + }; + + /* output: nodes */ +-static const desc_node output_nodes[] = { ++static const desc_node glue(output_nodes_, PARAM)[] = { + { + .nid = AC_NODE_ROOT, + .name = "root", +- .params = output_params_root, +- .nparams = ARRAY_SIZE(output_params_root), ++ .params = glue(output_params_root_, PARAM), ++ .nparams = ARRAY_SIZE(glue(output_params_root_, PARAM)), + },{ + .nid = 1, + .name = "func", +- .params = output_params_audio_func, +- .nparams = ARRAY_SIZE(output_params_audio_func), ++ .params = glue(output_params_audio_func_, PARAM), ++ .nparams = ARRAY_SIZE(glue(output_params_audio_func_, PARAM)), + },{ + .nid = 2, + .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .params = glue(common_params_audio_dac_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), + .stindex = 0, + },{ + .nid = 3, + .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .params = glue(common_params_audio_lineout_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), + .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | + (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | + (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +@@ -219,15 +219,15 @@ static const desc_node output_nodes[] = { + }; + + /* output: codec */ +-static const desc_codec output = { ++static const desc_codec glue(output_, PARAM) = { + .name = "output", + .iid = QEMU_HDA_ID_OUTPUT, +- .nodes = output_nodes, +- .nnodes = ARRAY_SIZE(output_nodes), ++ .nodes = glue(output_nodes_, PARAM), ++ .nnodes = ARRAY_SIZE(glue(output_nodes_, PARAM)), + }; + + /* duplex: root node */ +-static const desc_param duplex_params_root[] = { ++static const desc_param glue(duplex_params_root_, PARAM)[] = { + { + .id = AC_PAR_VENDOR_ID, + .val = QEMU_HDA_ID_DUPLEX, +@@ -244,7 +244,7 @@ static const desc_param duplex_params_root[] = { + }; + + /* duplex: audio function */ +-static const desc_param duplex_params_audio_func[] = { ++static const desc_param glue(duplex_params_audio_func_, PARAM)[] = { + { + .id = AC_PAR_FUNCTION_TYPE, + .val = AC_GRP_AUDIO_FUNCTION, +@@ -279,28 +279,28 @@ static const desc_param duplex_params_audio_func[] = { + }; + + /* duplex: nodes */ +-static const desc_node duplex_nodes[] = { ++static const desc_node glue(duplex_nodes_, PARAM)[] = { + { + .nid = AC_NODE_ROOT, + .name = "root", +- .params = duplex_params_root, +- .nparams = ARRAY_SIZE(duplex_params_root), ++ .params = glue(duplex_params_root_, PARAM), ++ .nparams = ARRAY_SIZE(glue(duplex_params_root_, PARAM)), + },{ + .nid = 1, + .name = "func", +- .params = duplex_params_audio_func, +- .nparams = ARRAY_SIZE(duplex_params_audio_func), ++ .params = glue(duplex_params_audio_func_, PARAM), ++ .nparams = ARRAY_SIZE(glue(duplex_params_audio_func_, PARAM)), + },{ + .nid = 2, + .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .params = glue(common_params_audio_dac_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), + .stindex = 0, + },{ + .nid = 3, + .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .params = glue(common_params_audio_lineout_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), + .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | + (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | + (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +@@ -311,15 +311,15 @@ static const desc_node duplex_nodes[] = { + },{ + .nid = 4, + .name = "adc", +- .params = common_params_audio_adc, +- .nparams = ARRAY_SIZE(common_params_audio_adc), ++ .params = glue(common_params_audio_adc_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)), + .stindex = 1, + .conn = (uint32_t[]) { 5 }, + },{ + .nid = 5, + .name = "in", +- .params = common_params_audio_linein, +- .nparams = ARRAY_SIZE(common_params_audio_linein), ++ .params = glue(common_params_audio_linein_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)), + .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | + (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) | + (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +@@ -330,15 +330,15 @@ static const desc_node duplex_nodes[] = { + }; + + /* duplex: codec */ +-static const desc_codec duplex = { ++static const desc_codec glue(duplex_, PARAM) = { + .name = "duplex", + .iid = QEMU_HDA_ID_DUPLEX, +- .nodes = duplex_nodes, +- .nnodes = ARRAY_SIZE(duplex_nodes), ++ .nodes = glue(duplex_nodes_, PARAM), ++ .nnodes = ARRAY_SIZE(glue(duplex_nodes_, PARAM)), + }; + + /* micro: root node */ +-static const desc_param micro_params_root[] = { ++static const desc_param glue(micro_params_root_, PARAM)[] = { + { + .id = AC_PAR_VENDOR_ID, + .val = QEMU_HDA_ID_MICRO, +@@ -355,7 +355,7 @@ static const desc_param micro_params_root[] = { + }; + + /* micro: audio function */ +-static const desc_param micro_params_audio_func[] = { ++static const desc_param glue(micro_params_audio_func_, PARAM)[] = { + { + .id = AC_PAR_FUNCTION_TYPE, + .val = AC_GRP_AUDIO_FUNCTION, +@@ -390,28 +390,28 @@ static const desc_param micro_params_audio_func[] = { + }; + + /* micro: nodes */ +-static const desc_node micro_nodes[] = { ++static const desc_node glue(micro_nodes_, PARAM)[] = { + { + .nid = AC_NODE_ROOT, + .name = "root", +- .params = micro_params_root, +- .nparams = ARRAY_SIZE(micro_params_root), ++ .params = glue(micro_params_root_, PARAM), ++ .nparams = ARRAY_SIZE(glue(micro_params_root_, PARAM)), + },{ + .nid = 1, + .name = "func", +- .params = micro_params_audio_func, +- .nparams = ARRAY_SIZE(micro_params_audio_func), ++ .params = glue(micro_params_audio_func_, PARAM), ++ .nparams = ARRAY_SIZE(glue(micro_params_audio_func_, PARAM)), + },{ + .nid = 2, + .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .params = glue(common_params_audio_dac_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_dac_, PARAM)), + .stindex = 0, + },{ + .nid = 3, + .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .params = glue(common_params_audio_lineout_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_lineout_, PARAM)), + .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | + (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) | + (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +@@ -422,15 +422,15 @@ static const desc_node micro_nodes[] = { + },{ + .nid = 4, + .name = "adc", +- .params = common_params_audio_adc, +- .nparams = ARRAY_SIZE(common_params_audio_adc), ++ .params = glue(common_params_audio_adc_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_adc_, PARAM)), + .stindex = 1, + .conn = (uint32_t[]) { 5 }, + },{ + .nid = 5, + .name = "in", +- .params = common_params_audio_linein, +- .nparams = ARRAY_SIZE(common_params_audio_linein), ++ .params = glue(common_params_audio_linein_, PARAM), ++ .nparams = ARRAY_SIZE(glue(common_params_audio_linein_, PARAM)), + .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | + (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) | + (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +@@ -441,9 +441,16 @@ static const desc_node micro_nodes[] = { + }; + + /* micro: codec */ +-static const desc_codec micro = { ++static const desc_codec glue(micro_, PARAM) = { + .name = "micro", + .iid = QEMU_HDA_ID_MICRO, +- .nodes = micro_nodes, +- .nnodes = ARRAY_SIZE(micro_nodes), ++ .nodes = glue(micro_nodes_, PARAM), ++ .nnodes = ARRAY_SIZE(glue(micro_nodes_, PARAM)), + }; ++ ++#undef PARAM ++#undef HDA_MIXER ++#undef QEMU_HDA_ID_OUTPUT ++#undef QEMU_HDA_ID_DUPLEX ++#undef QEMU_HDA_ID_MICRO ++#undef QEMU_HDA_AMP_CAPS +diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c +index cb498fc..3217d90 100644 +--- a/hw/audio/hda-codec.c ++++ b/hw/audio/hda-codec.c +@@ -118,7 +118,15 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as) + #define QEMU_HDA_AMP_NONE (0) + #define QEMU_HDA_AMP_STEPS 0x4a + ++#ifdef CONFIG_MIXEMU ++#define PARAM mixemu ++#define HDA_MIXER + #include "hda-codec-common.h" ++#endif ++ ++#define PARAM nomixemu ++#include "hda-codec-common.h" ++ + /* -------------------------------------------------------------------------- */ + + static const char *fmt2name[] = { +@@ -163,6 +171,7 @@ struct HDAAudioState { + + /* properties */ + uint32_t debug; ++ bool mixer; + }; + + static void hda_audio_input_cb(void *opaque, int avail) +@@ -584,23 +593,70 @@ static const VMStateDescription vmstate_hda_audio = { + }; + + static Property hda_audio_properties[] = { +- DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), ++ DEFINE_PROP_UINT32("debug", HDAAudioState, debug, 0), ++#ifdef CONFIG_MIXEMU ++ DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, true), ++#else ++ DEFINE_PROP_BOOL("mixer", HDAAudioState, mixer, false), ++#endif + DEFINE_PROP_END_OF_LIST(), + }; + + static int hda_audio_init_output(HDACodecDevice *hda) + { +- return hda_audio_init(hda, &output); ++ HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda); ++ ++ if (!a->mixer) { ++ return hda_audio_init(hda, &output_nomixemu); ++ } else { ++ ++#ifdef CONFIG_MIXEMU ++ return hda_audio_init(hda, &output_mixemu); ++#else ++ fprintf(stderr, "ERROR: " ++ "hda-codec : Mixer emulation has not been compiled in!\n"); ++ return -1; ++#endif ++ ++ } + } + + static int hda_audio_init_duplex(HDACodecDevice *hda) + { +- return hda_audio_init(hda, &duplex); ++ HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda); ++ ++ if (!a->mixer) { ++ return hda_audio_init(hda, &duplex_nomixemu); ++ } else { ++ ++#ifdef CONFIG_MIXEMU ++ return hda_audio_init(hda, &duplex_mixemu); ++#else ++ fprintf(stderr, "ERROR: " ++ "hda-codec : Mixer emulation has not been compiled in!\n"); ++ return -1; ++#endif ++ ++ } + } + + static int hda_audio_init_micro(HDACodecDevice *hda) + { +- return hda_audio_init(hda, µ); ++ HDAAudioState *a = DO_UPCAST(HDAAudioState, hda, hda); ++ ++ if (!a->mixer) { ++ return hda_audio_init(hda, µ_nomixemu); ++ } else { ++ ++#ifdef CONFIG_MIXEMU ++ return hda_audio_init(hda, µ_mixemu); ++#else ++ fprintf(stderr, "ERROR: " ++ "hda-codec : Mixer emulation has not been compiled in!\n"); ++ return -1; ++#endif ++ ++ } + } + + static void hda_audio_output_class_init(ObjectClass *klass, void *data) +-- +1.7.1 + diff --git a/SOURCES/kvm-hda-codec-refactor-common-definitions-into-a-header-.patch b/SOURCES/kvm-hda-codec-refactor-common-definitions-into-a-header-.patch new file mode 100644 index 0000000..5efe384 --- /dev/null +++ b/SOURCES/kvm-hda-codec-refactor-common-definitions-into-a-header-.patch @@ -0,0 +1,927 @@ +From 05205ba1d42e1381c4b0ecee32dd34535a68dace Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Tue, 15 Oct 2013 17:10:58 +0200 +Subject: [PATCH 21/25] hda-codec: refactor common definitions into a header file + +RH-Author: Bandan Das +Message-id: <1381857067-9399-2-git-send-email-bsd@redhat.com> +Patchwork-id: 54949 +O-Subject: [PATCH RHEL-7 qemu-kvm v3 1/5] hda-codec: refactor common definitions into a header file +Bugzilla: 954195 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster + +Move common defines and structs to a header file. +The next commit will include it twice, once for a device with a +mixer, and once for device without a mixer. + +Signed-off-by: Bandan Das +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 7953793c033343dbea97836645edbe4e61754b11) +--- + hw/audio/hda-codec-common.h | 449 ++++++++++++++++++++++++++++++++++++++++++++ + hw/audio/hda-codec.c | 424 +---------------------------------------- + 2 files changed, 450 insertions(+), 423 deletions(-) + create mode 100644 hw/audio/hda-codec-common.h + +Signed-off-by: Miroslav Rezanina +--- + hw/audio/hda-codec-common.h | 449 +++++++++++++++++++++++++++++++++++++++++++ + hw/audio/hda-codec.c | 424 +---------------------------------------- + 2 files changed, 450 insertions(+), 423 deletions(-) + create mode 100644 hw/audio/hda-codec-common.h + +diff --git a/hw/audio/hda-codec-common.h b/hw/audio/hda-codec-common.h +new file mode 100644 +index 0000000..2f7e95f +--- /dev/null ++++ b/hw/audio/hda-codec-common.h +@@ -0,0 +1,449 @@ ++/* ++ * Common code to disable/enable mixer emulation at run time ++ * ++ * Copyright (C) 2013 Red Hat, Inc. ++ * ++ * Written by Bandan Das ++ * with important bits picked up from hda-codec.c ++ * ++ * 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 or ++ * (at your option) version 3 of the License. ++ * ++ * 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 . ++ */ ++ ++/* ++ * HDA codec descriptions ++ */ ++ ++#ifdef CONFIG_MIXEMU ++#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12) ++#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22) ++#define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32) ++#define QEMU_HDA_AMP_CAPS \ ++ (AC_AMPCAP_MUTE | \ ++ (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \ ++ (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \ ++ (3 << AC_AMPCAP_STEP_SIZE_SHIFT)) ++#else ++#define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11) ++#define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21) ++#define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31) ++#define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE ++#endif ++ ++ ++/* common: audio output widget */ ++static const desc_param common_params_audio_dac[] = { ++ { ++ .id = AC_PAR_AUDIO_WIDGET_CAP, ++ .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) | ++ AC_WCAP_FORMAT_OVRD | ++ AC_WCAP_AMP_OVRD | ++ AC_WCAP_OUT_AMP | ++ AC_WCAP_STEREO), ++ },{ ++ .id = AC_PAR_PCM, ++ .val = QEMU_HDA_PCM_FORMATS, ++ },{ ++ .id = AC_PAR_STREAM, ++ .val = AC_SUPFMT_PCM, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_CAPS, ++ }, ++}; ++ ++/* common: audio input widget */ ++static const desc_param common_params_audio_adc[] = { ++ { ++ .id = AC_PAR_AUDIO_WIDGET_CAP, ++ .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) | ++ AC_WCAP_CONN_LIST | ++ AC_WCAP_FORMAT_OVRD | ++ AC_WCAP_AMP_OVRD | ++ AC_WCAP_IN_AMP | ++ AC_WCAP_STEREO), ++ },{ ++ .id = AC_PAR_CONNLIST_LEN, ++ .val = 1, ++ },{ ++ .id = AC_PAR_PCM, ++ .val = QEMU_HDA_PCM_FORMATS, ++ },{ ++ .id = AC_PAR_STREAM, ++ .val = AC_SUPFMT_PCM, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_CAPS, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ }, ++}; ++ ++/* common: pin widget (line-out) */ ++static const desc_param common_params_audio_lineout[] = { ++ { ++ .id = AC_PAR_AUDIO_WIDGET_CAP, ++ .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | ++ AC_WCAP_CONN_LIST | ++ AC_WCAP_STEREO), ++ },{ ++ .id = AC_PAR_PIN_CAP, ++ .val = AC_PINCAP_OUT, ++ },{ ++ .id = AC_PAR_CONNLIST_LEN, ++ .val = 1, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ }, ++}; ++ ++/* common: pin widget (line-in) */ ++static const desc_param common_params_audio_linein[] = { ++ { ++ .id = AC_PAR_AUDIO_WIDGET_CAP, ++ .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | ++ AC_WCAP_STEREO), ++ },{ ++ .id = AC_PAR_PIN_CAP, ++ .val = AC_PINCAP_IN, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ }, ++}; ++ ++/* output: root node */ ++static const desc_param output_params_root[] = { ++ { ++ .id = AC_PAR_VENDOR_ID, ++ .val = QEMU_HDA_ID_OUTPUT, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_OUTPUT, ++ },{ ++ .id = AC_PAR_REV_ID, ++ .val = 0x00100101, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00010001, ++ }, ++}; ++ ++/* output: audio function */ ++static const desc_param output_params_audio_func[] = { ++ { ++ .id = AC_PAR_FUNCTION_TYPE, ++ .val = AC_GRP_AUDIO_FUNCTION, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_OUTPUT, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00020002, ++ },{ ++ .id = AC_PAR_PCM, ++ .val = QEMU_HDA_PCM_FORMATS, ++ },{ ++ .id = AC_PAR_STREAM, ++ .val = AC_SUPFMT_PCM, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_GPIO_CAP, ++ .val = 0, ++ },{ ++ .id = AC_PAR_AUDIO_FG_CAP, ++ .val = 0x00000808, ++ },{ ++ .id = AC_PAR_POWER_STATE, ++ .val = 0, ++ }, ++}; ++ ++/* output: nodes */ ++static const desc_node output_nodes[] = { ++ { ++ .nid = AC_NODE_ROOT, ++ .name = "root", ++ .params = output_params_root, ++ .nparams = ARRAY_SIZE(output_params_root), ++ },{ ++ .nid = 1, ++ .name = "func", ++ .params = output_params_audio_func, ++ .nparams = ARRAY_SIZE(output_params_audio_func), ++ },{ ++ .nid = 2, ++ .name = "dac", ++ .params = common_params_audio_dac, ++ .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .stindex = 0, ++ },{ ++ .nid = 3, ++ .name = "out", ++ .params = common_params_audio_lineout, ++ .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | ++ (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | ++ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | ++ (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | ++ 0x10), ++ .pinctl = AC_PINCTL_OUT_EN, ++ .conn = (uint32_t[]) { 2 }, ++ } ++}; ++ ++/* output: codec */ ++static const desc_codec output = { ++ .name = "output", ++ .iid = QEMU_HDA_ID_OUTPUT, ++ .nodes = output_nodes, ++ .nnodes = ARRAY_SIZE(output_nodes), ++}; ++ ++/* duplex: root node */ ++static const desc_param duplex_params_root[] = { ++ { ++ .id = AC_PAR_VENDOR_ID, ++ .val = QEMU_HDA_ID_DUPLEX, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_DUPLEX, ++ },{ ++ .id = AC_PAR_REV_ID, ++ .val = 0x00100101, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00010001, ++ }, ++}; ++ ++/* duplex: audio function */ ++static const desc_param duplex_params_audio_func[] = { ++ { ++ .id = AC_PAR_FUNCTION_TYPE, ++ .val = AC_GRP_AUDIO_FUNCTION, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_DUPLEX, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00020004, ++ },{ ++ .id = AC_PAR_PCM, ++ .val = QEMU_HDA_PCM_FORMATS, ++ },{ ++ .id = AC_PAR_STREAM, ++ .val = AC_SUPFMT_PCM, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_GPIO_CAP, ++ .val = 0, ++ },{ ++ .id = AC_PAR_AUDIO_FG_CAP, ++ .val = 0x00000808, ++ },{ ++ .id = AC_PAR_POWER_STATE, ++ .val = 0, ++ }, ++}; ++ ++/* duplex: nodes */ ++static const desc_node duplex_nodes[] = { ++ { ++ .nid = AC_NODE_ROOT, ++ .name = "root", ++ .params = duplex_params_root, ++ .nparams = ARRAY_SIZE(duplex_params_root), ++ },{ ++ .nid = 1, ++ .name = "func", ++ .params = duplex_params_audio_func, ++ .nparams = ARRAY_SIZE(duplex_params_audio_func), ++ },{ ++ .nid = 2, ++ .name = "dac", ++ .params = common_params_audio_dac, ++ .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .stindex = 0, ++ },{ ++ .nid = 3, ++ .name = "out", ++ .params = common_params_audio_lineout, ++ .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | ++ (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | ++ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | ++ (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | ++ 0x10), ++ .pinctl = AC_PINCTL_OUT_EN, ++ .conn = (uint32_t[]) { 2 }, ++ },{ ++ .nid = 4, ++ .name = "adc", ++ .params = common_params_audio_adc, ++ .nparams = ARRAY_SIZE(common_params_audio_adc), ++ .stindex = 1, ++ .conn = (uint32_t[]) { 5 }, ++ },{ ++ .nid = 5, ++ .name = "in", ++ .params = common_params_audio_linein, ++ .nparams = ARRAY_SIZE(common_params_audio_linein), ++ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | ++ (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) | ++ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | ++ (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | ++ 0x20), ++ .pinctl = AC_PINCTL_IN_EN, ++ } ++}; ++ ++/* duplex: codec */ ++static const desc_codec duplex = { ++ .name = "duplex", ++ .iid = QEMU_HDA_ID_DUPLEX, ++ .nodes = duplex_nodes, ++ .nnodes = ARRAY_SIZE(duplex_nodes), ++}; ++ ++/* micro: root node */ ++static const desc_param micro_params_root[] = { ++ { ++ .id = AC_PAR_VENDOR_ID, ++ .val = QEMU_HDA_ID_MICRO, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_MICRO, ++ },{ ++ .id = AC_PAR_REV_ID, ++ .val = 0x00100101, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00010001, ++ }, ++}; ++ ++/* micro: audio function */ ++static const desc_param micro_params_audio_func[] = { ++ { ++ .id = AC_PAR_FUNCTION_TYPE, ++ .val = AC_GRP_AUDIO_FUNCTION, ++ },{ ++ .id = AC_PAR_SUBSYSTEM_ID, ++ .val = QEMU_HDA_ID_MICRO, ++ },{ ++ .id = AC_PAR_NODE_COUNT, ++ .val = 0x00020004, ++ },{ ++ .id = AC_PAR_PCM, ++ .val = QEMU_HDA_PCM_FORMATS, ++ },{ ++ .id = AC_PAR_STREAM, ++ .val = AC_SUPFMT_PCM, ++ },{ ++ .id = AC_PAR_AMP_IN_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_AMP_OUT_CAP, ++ .val = QEMU_HDA_AMP_NONE, ++ },{ ++ .id = AC_PAR_GPIO_CAP, ++ .val = 0, ++ },{ ++ .id = AC_PAR_AUDIO_FG_CAP, ++ .val = 0x00000808, ++ },{ ++ .id = AC_PAR_POWER_STATE, ++ .val = 0, ++ }, ++}; ++ ++/* micro: nodes */ ++static const desc_node micro_nodes[] = { ++ { ++ .nid = AC_NODE_ROOT, ++ .name = "root", ++ .params = micro_params_root, ++ .nparams = ARRAY_SIZE(micro_params_root), ++ },{ ++ .nid = 1, ++ .name = "func", ++ .params = micro_params_audio_func, ++ .nparams = ARRAY_SIZE(micro_params_audio_func), ++ },{ ++ .nid = 2, ++ .name = "dac", ++ .params = common_params_audio_dac, ++ .nparams = ARRAY_SIZE(common_params_audio_dac), ++ .stindex = 0, ++ },{ ++ .nid = 3, ++ .name = "out", ++ .params = common_params_audio_lineout, ++ .nparams = ARRAY_SIZE(common_params_audio_lineout), ++ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | ++ (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) | ++ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | ++ (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | ++ 0x10), ++ .pinctl = AC_PINCTL_OUT_EN, ++ .conn = (uint32_t[]) { 2 }, ++ },{ ++ .nid = 4, ++ .name = "adc", ++ .params = common_params_audio_adc, ++ .nparams = ARRAY_SIZE(common_params_audio_adc), ++ .stindex = 1, ++ .conn = (uint32_t[]) { 5 }, ++ },{ ++ .nid = 5, ++ .name = "in", ++ .params = common_params_audio_linein, ++ .nparams = ARRAY_SIZE(common_params_audio_linein), ++ .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | ++ (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) | ++ (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | ++ (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | ++ 0x20), ++ .pinctl = AC_PINCTL_IN_EN, ++ } ++}; ++ ++/* micro: codec */ ++static const desc_codec micro = { ++ .name = "micro", ++ .iid = QEMU_HDA_ID_MICRO, ++ .nodes = micro_nodes, ++ .nnodes = ARRAY_SIZE(micro_nodes), ++}; +diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c +index 362d8c0..cb498fc 100644 +--- a/hw/audio/hda-codec.c ++++ b/hw/audio/hda-codec.c +@@ -118,429 +118,7 @@ static void hda_codec_parse_fmt(uint32_t format, struct audsettings *as) + #define QEMU_HDA_AMP_NONE (0) + #define QEMU_HDA_AMP_STEPS 0x4a + +-#ifdef CONFIG_MIXEMU +-# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x12) +-# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x22) +-# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x32) +-# define QEMU_HDA_AMP_CAPS \ +- (AC_AMPCAP_MUTE | \ +- (QEMU_HDA_AMP_STEPS << AC_AMPCAP_OFFSET_SHIFT) | \ +- (QEMU_HDA_AMP_STEPS << AC_AMPCAP_NUM_STEPS_SHIFT) | \ +- (3 << AC_AMPCAP_STEP_SIZE_SHIFT)) +-#else +-# define QEMU_HDA_ID_OUTPUT ((QEMU_HDA_ID_VENDOR << 16) | 0x11) +-# define QEMU_HDA_ID_DUPLEX ((QEMU_HDA_ID_VENDOR << 16) | 0x21) +-# define QEMU_HDA_ID_MICRO ((QEMU_HDA_ID_VENDOR << 16) | 0x31) +-# define QEMU_HDA_AMP_CAPS QEMU_HDA_AMP_NONE +-#endif +- +-/* common: audio output widget */ +-static const desc_param common_params_audio_dac[] = { +- { +- .id = AC_PAR_AUDIO_WIDGET_CAP, +- .val = ((AC_WID_AUD_OUT << AC_WCAP_TYPE_SHIFT) | +- AC_WCAP_FORMAT_OVRD | +- AC_WCAP_AMP_OVRD | +- AC_WCAP_OUT_AMP | +- AC_WCAP_STEREO), +- },{ +- .id = AC_PAR_PCM, +- .val = QEMU_HDA_PCM_FORMATS, +- },{ +- .id = AC_PAR_STREAM, +- .val = AC_SUPFMT_PCM, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_CAPS, +- }, +-}; +- +-/* common: audio input widget */ +-static const desc_param common_params_audio_adc[] = { +- { +- .id = AC_PAR_AUDIO_WIDGET_CAP, +- .val = ((AC_WID_AUD_IN << AC_WCAP_TYPE_SHIFT) | +- AC_WCAP_CONN_LIST | +- AC_WCAP_FORMAT_OVRD | +- AC_WCAP_AMP_OVRD | +- AC_WCAP_IN_AMP | +- AC_WCAP_STEREO), +- },{ +- .id = AC_PAR_CONNLIST_LEN, +- .val = 1, +- },{ +- .id = AC_PAR_PCM, +- .val = QEMU_HDA_PCM_FORMATS, +- },{ +- .id = AC_PAR_STREAM, +- .val = AC_SUPFMT_PCM, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_CAPS, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- }, +-}; +- +-/* common: pin widget (line-out) */ +-static const desc_param common_params_audio_lineout[] = { +- { +- .id = AC_PAR_AUDIO_WIDGET_CAP, +- .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | +- AC_WCAP_CONN_LIST | +- AC_WCAP_STEREO), +- },{ +- .id = AC_PAR_PIN_CAP, +- .val = AC_PINCAP_OUT, +- },{ +- .id = AC_PAR_CONNLIST_LEN, +- .val = 1, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- }, +-}; +- +-/* common: pin widget (line-in) */ +-static const desc_param common_params_audio_linein[] = { +- { +- .id = AC_PAR_AUDIO_WIDGET_CAP, +- .val = ((AC_WID_PIN << AC_WCAP_TYPE_SHIFT) | +- AC_WCAP_STEREO), +- },{ +- .id = AC_PAR_PIN_CAP, +- .val = AC_PINCAP_IN, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- }, +-}; +- +-/* output: root node */ +-static const desc_param output_params_root[] = { +- { +- .id = AC_PAR_VENDOR_ID, +- .val = QEMU_HDA_ID_OUTPUT, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_OUTPUT, +- },{ +- .id = AC_PAR_REV_ID, +- .val = 0x00100101, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00010001, +- }, +-}; +- +-/* output: audio function */ +-static const desc_param output_params_audio_func[] = { +- { +- .id = AC_PAR_FUNCTION_TYPE, +- .val = AC_GRP_AUDIO_FUNCTION, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_OUTPUT, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00020002, +- },{ +- .id = AC_PAR_PCM, +- .val = QEMU_HDA_PCM_FORMATS, +- },{ +- .id = AC_PAR_STREAM, +- .val = AC_SUPFMT_PCM, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_GPIO_CAP, +- .val = 0, +- },{ +- .id = AC_PAR_AUDIO_FG_CAP, +- .val = 0x00000808, +- },{ +- .id = AC_PAR_POWER_STATE, +- .val = 0, +- }, +-}; +- +-/* output: nodes */ +-static const desc_node output_nodes[] = { +- { +- .nid = AC_NODE_ROOT, +- .name = "root", +- .params = output_params_root, +- .nparams = ARRAY_SIZE(output_params_root), +- },{ +- .nid = 1, +- .name = "func", +- .params = output_params_audio_func, +- .nparams = ARRAY_SIZE(output_params_audio_func), +- },{ +- .nid = 2, +- .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), +- .stindex = 0, +- },{ +- .nid = 3, +- .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), +- .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | +- (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | +- (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +- (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | +- 0x10), +- .pinctl = AC_PINCTL_OUT_EN, +- .conn = (uint32_t[]) { 2 }, +- } +-}; +- +-/* output: codec */ +-static const desc_codec output = { +- .name = "output", +- .iid = QEMU_HDA_ID_OUTPUT, +- .nodes = output_nodes, +- .nnodes = ARRAY_SIZE(output_nodes), +-}; +- +-/* duplex: root node */ +-static const desc_param duplex_params_root[] = { +- { +- .id = AC_PAR_VENDOR_ID, +- .val = QEMU_HDA_ID_DUPLEX, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_DUPLEX, +- },{ +- .id = AC_PAR_REV_ID, +- .val = 0x00100101, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00010001, +- }, +-}; +- +-/* duplex: audio function */ +-static const desc_param duplex_params_audio_func[] = { +- { +- .id = AC_PAR_FUNCTION_TYPE, +- .val = AC_GRP_AUDIO_FUNCTION, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_DUPLEX, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00020004, +- },{ +- .id = AC_PAR_PCM, +- .val = QEMU_HDA_PCM_FORMATS, +- },{ +- .id = AC_PAR_STREAM, +- .val = AC_SUPFMT_PCM, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_GPIO_CAP, +- .val = 0, +- },{ +- .id = AC_PAR_AUDIO_FG_CAP, +- .val = 0x00000808, +- },{ +- .id = AC_PAR_POWER_STATE, +- .val = 0, +- }, +-}; +- +-/* duplex: nodes */ +-static const desc_node duplex_nodes[] = { +- { +- .nid = AC_NODE_ROOT, +- .name = "root", +- .params = duplex_params_root, +- .nparams = ARRAY_SIZE(duplex_params_root), +- },{ +- .nid = 1, +- .name = "func", +- .params = duplex_params_audio_func, +- .nparams = ARRAY_SIZE(duplex_params_audio_func), +- },{ +- .nid = 2, +- .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), +- .stindex = 0, +- },{ +- .nid = 3, +- .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), +- .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | +- (AC_JACK_LINE_OUT << AC_DEFCFG_DEVICE_SHIFT) | +- (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +- (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | +- 0x10), +- .pinctl = AC_PINCTL_OUT_EN, +- .conn = (uint32_t[]) { 2 }, +- },{ +- .nid = 4, +- .name = "adc", +- .params = common_params_audio_adc, +- .nparams = ARRAY_SIZE(common_params_audio_adc), +- .stindex = 1, +- .conn = (uint32_t[]) { 5 }, +- },{ +- .nid = 5, +- .name = "in", +- .params = common_params_audio_linein, +- .nparams = ARRAY_SIZE(common_params_audio_linein), +- .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | +- (AC_JACK_LINE_IN << AC_DEFCFG_DEVICE_SHIFT) | +- (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +- (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | +- 0x20), +- .pinctl = AC_PINCTL_IN_EN, +- } +-}; +- +-/* duplex: codec */ +-static const desc_codec duplex = { +- .name = "duplex", +- .iid = QEMU_HDA_ID_DUPLEX, +- .nodes = duplex_nodes, +- .nnodes = ARRAY_SIZE(duplex_nodes), +-}; +- +-/* micro: root node */ +-static const desc_param micro_params_root[] = { +- { +- .id = AC_PAR_VENDOR_ID, +- .val = QEMU_HDA_ID_MICRO, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_MICRO, +- },{ +- .id = AC_PAR_REV_ID, +- .val = 0x00100101, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00010001, +- }, +-}; +- +-/* micro: audio function */ +-static const desc_param micro_params_audio_func[] = { +- { +- .id = AC_PAR_FUNCTION_TYPE, +- .val = AC_GRP_AUDIO_FUNCTION, +- },{ +- .id = AC_PAR_SUBSYSTEM_ID, +- .val = QEMU_HDA_ID_MICRO, +- },{ +- .id = AC_PAR_NODE_COUNT, +- .val = 0x00020004, +- },{ +- .id = AC_PAR_PCM, +- .val = QEMU_HDA_PCM_FORMATS, +- },{ +- .id = AC_PAR_STREAM, +- .val = AC_SUPFMT_PCM, +- },{ +- .id = AC_PAR_AMP_IN_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_AMP_OUT_CAP, +- .val = QEMU_HDA_AMP_NONE, +- },{ +- .id = AC_PAR_GPIO_CAP, +- .val = 0, +- },{ +- .id = AC_PAR_AUDIO_FG_CAP, +- .val = 0x00000808, +- },{ +- .id = AC_PAR_POWER_STATE, +- .val = 0, +- }, +-}; +- +-/* micro: nodes */ +-static const desc_node micro_nodes[] = { +- { +- .nid = AC_NODE_ROOT, +- .name = "root", +- .params = micro_params_root, +- .nparams = ARRAY_SIZE(micro_params_root), +- },{ +- .nid = 1, +- .name = "func", +- .params = micro_params_audio_func, +- .nparams = ARRAY_SIZE(micro_params_audio_func), +- },{ +- .nid = 2, +- .name = "dac", +- .params = common_params_audio_dac, +- .nparams = ARRAY_SIZE(common_params_audio_dac), +- .stindex = 0, +- },{ +- .nid = 3, +- .name = "out", +- .params = common_params_audio_lineout, +- .nparams = ARRAY_SIZE(common_params_audio_lineout), +- .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | +- (AC_JACK_SPEAKER << AC_DEFCFG_DEVICE_SHIFT) | +- (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +- (AC_JACK_COLOR_GREEN << AC_DEFCFG_COLOR_SHIFT) | +- 0x10), +- .pinctl = AC_PINCTL_OUT_EN, +- .conn = (uint32_t[]) { 2 }, +- },{ +- .nid = 4, +- .name = "adc", +- .params = common_params_audio_adc, +- .nparams = ARRAY_SIZE(common_params_audio_adc), +- .stindex = 1, +- .conn = (uint32_t[]) { 5 }, +- },{ +- .nid = 5, +- .name = "in", +- .params = common_params_audio_linein, +- .nparams = ARRAY_SIZE(common_params_audio_linein), +- .config = ((AC_JACK_PORT_COMPLEX << AC_DEFCFG_PORT_CONN_SHIFT) | +- (AC_JACK_MIC_IN << AC_DEFCFG_DEVICE_SHIFT) | +- (AC_JACK_CONN_UNKNOWN << AC_DEFCFG_CONN_TYPE_SHIFT) | +- (AC_JACK_COLOR_RED << AC_DEFCFG_COLOR_SHIFT) | +- 0x20), +- .pinctl = AC_PINCTL_IN_EN, +- } +-}; +- +-/* micro: codec */ +-static const desc_codec micro = { +- .name = "micro", +- .iid = QEMU_HDA_ID_MICRO, +- .nodes = micro_nodes, +- .nnodes = ARRAY_SIZE(micro_nodes), +-}; +- ++#include "hda-codec-common.h" + /* -------------------------------------------------------------------------- */ + + static const char *fmt2name[] = { +-- +1.7.1 + diff --git a/SOURCES/kvm-hw-Pass-QEMUMachine-to-its-init-method.patch b/SOURCES/kvm-hw-Pass-QEMUMachine-to-its-init-method.patch new file mode 100644 index 0000000..25b6ab4 --- /dev/null +++ b/SOURCES/kvm-hw-Pass-QEMUMachine-to-its-init-method.patch @@ -0,0 +1,88 @@ +From b63a24d9875589b40cad66a381b22f8304d0fdcd Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:25 +0100 +Subject: [PATCH 25/29] hw: Pass QEMUMachine to its init() method + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-9-git-send-email-armbru@redhat.com> +Patchwork-id: 55246 +O-Subject: [PATCH 7.0 qemu-kvm 08/11] hw: Pass QEMUMachine to its init() method +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Put it in QEMUMachineInitArgs, so I don't have to touch every board. + +Signed-off-by: Markus Armbruster +(cherry picked from pending upstream submission) + +Conflicts: + include/hw/boards.h + vl.c + +Conflicts because we don't have commit c165473 "hw: Clean up bogus +default boot order". +--- + include/hw/boards.h | 7 +++++-- + vl.c | 3 ++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/hw/boards.h | 7 +++++-- + vl.c | 3 ++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/include/hw/boards.h b/include/hw/boards.h +index fb7c6f1..dd65e30 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -9,7 +9,10 @@ + #define DEFAULT_MACHINE_OPTIONS \ + .boot_order = "cad" + ++typedef struct QEMUMachine QEMUMachine; ++ + typedef struct QEMUMachineInitArgs { ++ const QEMUMachine *machine; + ram_addr_t ram_size; + const char *boot_device; + const char *kernel_filename; +@@ -24,7 +27,7 @@ typedef void QEMUMachineResetFunc(void); + + typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp); + +-typedef struct QEMUMachine { ++struct QEMUMachine { + const char *name; + const char *alias; + const char *desc; +@@ -46,7 +49,7 @@ typedef struct QEMUMachine { + GlobalProperty *compat_props; + struct QEMUMachine *next; + const char *hw_version; +-} QEMUMachine; ++}; + + int qemu_register_machine(QEMUMachine *m); + QEMUMachine *find_default_machine(void); +diff --git a/vl.c b/vl.c +index 19cc3b2..7c8ba63 100644 +--- a/vl.c ++++ b/vl.c +@@ -4218,7 +4218,8 @@ int main(int argc, char **argv, char **envp) + + qdev_machine_init(); + +- QEMUMachineInitArgs args = { .ram_size = ram_size, ++ QEMUMachineInitArgs args = { .machine = machine, ++ .ram_size = ram_size, + .boot_device = boot_order, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, +-- +1.7.1 + diff --git a/SOURCES/kvm-hw-import-bitmap-operations-in-qdev-core-header.patch b/SOURCES/kvm-hw-import-bitmap-operations-in-qdev-core-header.patch new file mode 100644 index 0000000..5c52564 --- /dev/null +++ b/SOURCES/kvm-hw-import-bitmap-operations-in-qdev-core-header.patch @@ -0,0 +1,117 @@ +From 7d299e618bd3833b3874619d7b9b18b65dcc63e2 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:07 +0100 +Subject: [PATCH 31/81] hw: import bitmap operations in qdev-core header + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-3-git-send-email-kwolf@redhat.com> +Patchwork-id: 55528 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 02/17] hw: import bitmap operations in qdev-core header +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Marcel Apfelbaum + +Made small tweaks in code to prevent compilation issues +when importing qemu/bitmap.h in qdev-core + +Signed-off-by: Marcel Apfelbaum +Message-id: 1375107465-25767-2-git-send-email-marcel.a@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 949fc82314cc84162e64a5323764527a542421ce) +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/core/qdev-properties.c | 13 +++++++------ + hw/net/eepro100.c | 2 +- + include/hw/qdev-core.h | 1 + + 3 files changed, 9 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/core/qdev-properties.c | 13 +++++++------ + hw/net/eepro100.c | 2 +- + include/hw/qdev-core.h | 1 + + 3 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c +index 3a324fb..6e1ed1e 100644 +--- a/hw/core/qdev-properties.c ++++ b/hw/core/qdev-properties.c +@@ -74,13 +74,14 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val) + } + } + +-static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) ++static int prop_print_bit(DeviceState *dev, Property *prop, char *dest, ++ size_t len) + { + uint32_t *p = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off"); + } + +-static void get_bit(Object *obj, Visitor *v, void *opaque, ++static void prop_get_bit(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) + { + DeviceState *dev = DEVICE(obj); +@@ -91,7 +92,7 @@ static void get_bit(Object *obj, Visitor *v, void *opaque, + visit_type_bool(v, &value, name, errp); + } + +-static void set_bit(Object *obj, Visitor *v, void *opaque, ++static void prop_set_bit(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) + { + DeviceState *dev = DEVICE(obj); +@@ -115,9 +116,9 @@ static void set_bit(Object *obj, Visitor *v, void *opaque, + PropertyInfo qdev_prop_bit = { + .name = "boolean", + .legacy_name = "on/off", +- .print = print_bit, +- .get = get_bit, +- .set = set_bit, ++ .print = prop_print_bit, ++ .get = prop_get_bit, ++ .set = prop_set_bit, + }; + + /* --- bool --- */ +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index dc99ea6..b69cc60 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -47,6 +47,7 @@ + #include "hw/nvram/eeprom93xx.h" + #include "sysemu/sysemu.h" + #include "sysemu/dma.h" ++#include "qemu/bitops.h" + + /* QEMU sends frames smaller than 60 bytes to ethernet nics. + * Such frames are rejected by real nics and their emulations. +@@ -105,7 +106,6 @@ + #define PCI_IO_SIZE 64 + #define PCI_FLASH_SIZE (128 * KiB) + +-#define BIT(n) (1 << (n)) + #define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) + + /* The SCB accepts the following controls for the Tx and Rx units: */ +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index cf83d54..9d995bf 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -4,6 +4,7 @@ + #include "qemu/queue.h" + #include "qemu/option.h" + #include "qemu/typedefs.h" ++#include "qemu/bitmap.h" + #include "qom/object.h" + #include "hw/irq.h" + #include "qapi/error.h" +-- +1.7.1 + diff --git a/SOURCES/kvm-hw-misc-don-t-create-pvpanic-device-by-default.patch b/SOURCES/kvm-hw-misc-don-t-create-pvpanic-device-by-default.patch new file mode 100644 index 0000000..db7cee6 --- /dev/null +++ b/SOURCES/kvm-hw-misc-don-t-create-pvpanic-device-by-default.patch @@ -0,0 +1,207 @@ +From 45dc4ec297fdb6ba95e7a8c1f3d904fe88b0e282 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:37 +0100 +Subject: [PATCH 78/81] hw/misc: don't create pvpanic device by default + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-10-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55554 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 9/9] hw/misc: don't create pvpanic device by default +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +We don't need compatibility with 1.5 so we can simply +revert the patch creating it by default. + +This patch: + - reverts "pvpanic: create pvpanic by default for machine 1.5" + - removes cannot_instantiate_with_device_add_yet flag + +Closest upstream commit (currently in qemu-devl-list): + [Qemu-devel] [PATCH v2 1.7] pc: get rid of builtin pvpanic for "-M pc-1.5" + +Related upstream commit: + commit 7f3e341a008c585deed174eaf1f826c88c67948a + Author: Marcel Apfelbaum + Date: Sun Aug 11 18:10:42 2013 +0300 + + hw/misc: don't create pvpanic device by default + + This patch is based on Hu Tao's: + http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg00124.html + + No need to hard-code pvpanic as part of the machine. + It can be added with "-device pvpanic" from command line (The next patch). + Anyway, for backport compatibility it is still part of 1.5 + machine. + + Signed-off-by: Marcel Apfelbaum + Reviewed-by: Hu Tao + Message-id: 1376233843-19410-2-git-send-email-marcel.a@redhat.com + Signed-off-by: Anthony Liguori + +losest upstream patch: + +Signed-off-by: Marcel Apfelbaum +--- + hw/i386/pc_piix.c | 12 ------------ + hw/i386/pc_q35.c | 6 ------ + hw/misc/pvpanic.c | 11 ----------- + 3 files changed, 29 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 12 ------------ + hw/i386/pc_q35.c | 6 ------ + hw/misc/pvpanic.c | 11 ----------- + 3 files changed, 0 insertions(+), 29 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 825a5b1..2d8e79f 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -57,7 +57,6 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; + static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; + static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; + +-static bool has_pvpanic = true; + static bool smbios_type1_defaults = true; + + /* PC hardware initialisation */ +@@ -227,10 +226,6 @@ static void pc_init1(QEMUMachineInitArgs *args, + if (pci_enabled) { + pc_pci_device_init(pci_bus); + } +- +- if (has_pvpanic) { +- pvpanic_init(isa_bus); +- } + } + + static void pc_init_pci(QEMUMachineInitArgs *args) +@@ -242,7 +237,6 @@ static void pc_init_pci(QEMUMachineInitArgs *args) + + static void pc_init_pci_1_4(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; + x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); + x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); + pc_init_pci(args); +@@ -251,7 +245,6 @@ static void pc_init_pci_1_4(QEMUMachineInitArgs *args) + static void pc_init_pci_1_3(QEMUMachineInitArgs *args) + { + enable_compat_apic_id_mode(); +- has_pvpanic = false; + pc_init_pci(args); + } + +@@ -260,7 +253,6 @@ static void pc_init_pci_1_2(QEMUMachineInitArgs *args) + { + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- has_pvpanic = false; + pc_init_pci(args); + } + +@@ -269,14 +261,12 @@ static void pc_init_pci_1_0(QEMUMachineInitArgs *args) + { + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- has_pvpanic = false; + pc_init_pci(args); + } + + /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */ + static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); + pc_init1(args, get_system_memory(), get_system_io(), 1, 0); +@@ -284,7 +274,6 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) + + static void pc_init_isa(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; + if (!args->cpu_model) { + args->cpu_model = "486"; + } +@@ -931,7 +920,6 @@ static QEMUMachine pc_machine_rhel650 = { + + static void pc_init_rhel640(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; + x86_cpu_compat_set_features(NULL, FEAT_1_EDX, 0, CPUID_SEP); + pc_init_rhel650(args); + } +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 64995ac..f308098 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -47,7 +47,6 @@ + /* ICH9 AHCI has 6 ports */ + #define MAX_SATA_PORTS 6 + +-static bool has_pvpanic = true; + static bool smbios_type1_defaults = true; + + /* PC hardware initialisation */ +@@ -205,17 +204,12 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + if (pci_enabled) { + pc_pci_device_init(host_bus); + } +- +- if (has_pvpanic) { +- pvpanic_init(isa_bus); +- } + } + + #if 0 /* Disabled for Red Hat Enterprise Linux */ + + static void pc_q35_init_1_4(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; + x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); + x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); + pc_q35_init(args); +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index 1d3178d..1838bc7 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -19,7 +19,6 @@ + #include "qemu/log.h" + + #include "hw/nvram/fw_cfg.h" +-#include "hw/i386/pc.h" + + /* The bit of supported pv event */ + #define PVPANIC_F_PANICKED 0 +@@ -108,11 +107,6 @@ static int pvpanic_isa_initfn(ISADevice *dev) + return 0; + } + +-void pvpanic_init(ISABus *bus) +-{ +- isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE); +-} +- + static Property pvpanic_isa_properties[] = { + DEFINE_PROP_UINT16("ioport", PVPanicState, ioport, 0x505), + DEFINE_PROP_END_OF_LIST(), +@@ -125,11 +119,6 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data) + + ic->init = pvpanic_isa_initfn; + dc->props = pvpanic_isa_properties; +- /* +- * To be dropped in future backport of commit a5d3f64 "hw/misc: +- * make pvpanic known to user": +- */ +- dc->cannot_instantiate_with_device_add_yet = true; + } + + static TypeInfo pvpanic_isa_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-hw-misc-make-pvpanic-known-to-user.patch b/SOURCES/kvm-hw-misc-make-pvpanic-known-to-user.patch new file mode 100644 index 0000000..c67e357 --- /dev/null +++ b/SOURCES/kvm-hw-misc-make-pvpanic-known-to-user.patch @@ -0,0 +1,92 @@ +From b3f60a169126dd6a4ef7c64442494d943f9ffbd2 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:33 +0100 +Subject: [PATCH 74/81] hw/misc: make pvpanic known to user + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-6-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55550 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 5/9] hw/misc: make pvpanic known to user +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +This patch is based on Hu Tao's: +http://lists.nongnu.org/archive/html/qemu-devel/2013-08/msg00125.html + +The pvpanic device may be enabled now with "-device pvpanic" +from command line. + +Signed-off-by: Marcel Apfelbaum +Reviewed-by: Hu Tao +Message-id: 1376233843-19410-3-git-send-email-marcel.a@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit a5d3f640a0fa56eaed712c9361150568e32e1d08) +Signed-off-by: Marcel Apfelbaum + +Conflicts: + hw/misc/pvpanic.c + +Signed-off-by: Marcel Apfelbaum +--- + hw/misc/pvpanic.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/pvpanic.c | 28 ++++++++++++---------------- + 1 files changed, 12 insertions(+), 16 deletions(-) + +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index 1aab787..1d3178d 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -89,32 +89,28 @@ static const MemoryRegionOps pvpanic_ops = { + static int pvpanic_isa_initfn(ISADevice *dev) + { + PVPanicState *s = ISA_PVPANIC_DEVICE(dev); ++ FWCfgState *fw_cfg = fw_cfg_find(); ++ uint16_t *pvpanic_port; + +- memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1); +- isa_register_ioport(dev, &s->io, s->ioport); ++ if (!fw_cfg) { ++ return -1; ++ } + +- return 0; +-} ++ memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1); + +-static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg) +-{ +- PVPanicState *s = ISA_PVPANIC_DEVICE(dev); +- uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port)); ++ pvpanic_port = g_malloc(sizeof(*pvpanic_port)); + *pvpanic_port = cpu_to_le16(s->ioport); +- + fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, + sizeof(*pvpanic_port)); ++ ++ isa_register_ioport(dev, &s->io, s->ioport); ++ ++ return 0; + } + + void pvpanic_init(ISABus *bus) + { +- ISADevice *dev; +- FWCfgState *fw_cfg = fw_cfg_find(); +- if (!fw_cfg) { +- return; +- } +- dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE); +- pvpanic_fw_cfg(dev, fw_cfg); ++ isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE); + } + + static Property pvpanic_isa_properties[] = { +-- +1.7.1 + diff --git a/SOURCES/kvm-i386-fix-LAPIC-TSC-deadline-timer-save-restore.patch b/SOURCES/kvm-i386-fix-LAPIC-TSC-deadline-timer-save-restore.patch new file mode 100644 index 0000000..0785147 --- /dev/null +++ b/SOURCES/kvm-i386-fix-LAPIC-TSC-deadline-timer-save-restore.patch @@ -0,0 +1,90 @@ +From 12623687c4bd5eeb5b3ca8f23cf3b646357e2bc3 Mon Sep 17 00:00:00 2001 +From: Marcelo Tosatti +Date: Tue, 20 Aug 2013 21:42:24 +0200 +Subject: [PATCH 25/28] kvm: i386: fix LAPIC TSC deadline timer save/restore + +RH-Author: Marcelo Tosatti +Message-id: <20130820214224.GA9334@amt.cnet> +Patchwork-id: 53623 +O-Subject: [RHEL7 qemu-kvm PATCH] kvm: i386: fix LAPIC TSC deadline timer save/restore +Bugzilla: 972433 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Gleb Natapov + +BZ: 972433 + +commit 7477cd3897082d2650d520a4e9aa7f8affa3dd5d of uq/master branch +of qemu-kvm.git repository + +The configuration of the timer represented by MSR_IA32_TSCDEADLINE depends on: + +- APIC LVT Timer register. +- TSC value. + +Change the order to respect the dependency. + +Signed-off-by: Marcelo Tosatti +Signed-off-by: Paolo Bonzini +Signed-off-by: Miroslav Rezanina +--- + target-i386/kvm.c | 29 ++++++++++++++++++++++++++--- + 1 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index 8da6a0d..c5a9416 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -1042,6 +1042,26 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry, + entry->data = value; + } + ++static int kvm_put_tscdeadline_msr(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ struct { ++ struct kvm_msrs info; ++ struct kvm_msr_entry entries[1]; ++ } msr_data; ++ struct kvm_msr_entry *msrs = msr_data.entries; ++ ++ if (!has_msr_tsc_deadline) { ++ return 0; ++ } ++ ++ kvm_msr_entry_set(&msrs[0], MSR_IA32_TSCDEADLINE, env->tsc_deadline); ++ ++ msr_data.info.nmsrs = 1; ++ ++ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); ++} ++ + static int kvm_put_msrs(X86CPU *cpu, int level) + { + CPUX86State *env = &cpu->env; +@@ -1065,9 +1085,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + if (has_msr_tsc_adjust) { + kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust); + } +- if (has_msr_tsc_deadline) { +- kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline); +- } + if (has_msr_misc_enable) { + kvm_msr_entry_set(&msrs[n++], MSR_IA32_MISC_ENABLE, + env->msr_ia32_misc_enable); +@@ -1705,6 +1722,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + return ret; + } + } ++ ++ ret = kvm_put_tscdeadline_msr(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + ret = kvm_put_vcpu_events(x86_cpu, level); + if (ret < 0) { + return ret; +-- +1.7.1 + diff --git a/SOURCES/kvm-ich9-Document-why-cannot_instantiate_with_device_add.patch b/SOURCES/kvm-ich9-Document-why-cannot_instantiate_with_device_add.patch new file mode 100644 index 0000000..c934c45 --- /dev/null +++ b/SOURCES/kvm-ich9-Document-why-cannot_instantiate_with_device_add.patch @@ -0,0 +1,85 @@ +From 085e956d2dbbc280727760ffa620b8a22db1cb6e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:17 +0100 +Subject: [PATCH 41/81] ich9: Document why cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-13-git-send-email-kwolf@redhat.com> +Patchwork-id: 55538 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 12/17] ich9: Document why cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +An ICH9 southbridge contains several PCI devices, some of them with +multiple functions. We model each function as a separate qdev. Two +of them need some special wiring set up in pc_q35_init() to work: the +LPC controller at 00:1f.0, and the SMBus controller at 00:1f.3. + +Signed-off-by: Markus Armbruster +Reviewed-by: Peter Maydell +(cherry picked from pending upstream submission) +Signed-off-by: Kevin Wolf +--- + hw/i2c/smbus_ich9.c | 6 +++++- + hw/isa/lpc_ich9.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i2c/smbus_ich9.c | 6 +++++- + hw/isa/lpc_ich9.c | 7 +++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c +index c1ffa34..8d47eaf 100644 +--- a/hw/i2c/smbus_ich9.c ++++ b/hw/i2c/smbus_ich9.c +@@ -97,11 +97,15 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6; + k->revision = ICH9_A2_SMB_REVISION; + k->class_id = PCI_CLASS_SERIAL_SMBUS; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_ich9_smbus; + dc->desc = "ICH9 SMBUS Bridge"; + k->init = ich9_smbus_initfn; + k->config_write = ich9_smbus_write_config; ++ /* ++ * Reason: part of ICH9 southbridge, needs to be wired up by ++ * pc_q35_init() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base) +diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c +index 580e9ac..4f834b9 100644 +--- a/hw/isa/lpc_ich9.c ++++ b/hw/isa/lpc_ich9.c +@@ -603,14 +603,17 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) + dc->reset = ich9_lpc_reset; + k->init = ich9_lpc_initfn; + dc->vmsd = &vmstate_ich9_lpc; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->config_write = ich9_lpc_config_write; + dc->desc = "ICH9 LPC bridge"; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_ICH9_8; + k->revision = ICH9_A2_LPC_REVISION; + k->class_id = PCI_CLASS_BRIDGE_ISA; +- ++ /* ++ * Reason: part of ICH9 southbridge, needs to be wired up by ++ * pc_q35_init() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo ich9_lpc_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-isa-Clean-up-use-of-cannot_instantiate_with_device_a.patch b/SOURCES/kvm-isa-Clean-up-use-of-cannot_instantiate_with_device_a.patch new file mode 100644 index 0000000..efac809 --- /dev/null +++ b/SOURCES/kvm-isa-Clean-up-use-of-cannot_instantiate_with_device_a.patch @@ -0,0 +1,280 @@ +From 7e9beb48fd9438354ea6d6747cbbefdc3b553590 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:20 +0100 +Subject: [PATCH 44/81] isa: Clean up use of cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-16-git-send-email-kwolf@redhat.com> +Patchwork-id: 55541 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 15/17] isa: Clean up use of cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Drop it when there's no obvious reason why device_add could not work. +Else keep and document why. + +* isa-fdc: drop + +* i8042: drop, even though its I/O base is hardcoded (because you + could conceivably still add one to a board that has none), and even + though PC board code wires up the A20 line (because that wiring is + optional) + +* port92: keep because it needs additional wiring by port92_init() + +* mc146818rtc: keep because it needs to be wired up by rtc_init() + +* m48t59_isa: keep because needs to be wired up by m48t59_init_isa() + +* isa-pit, kvm-pit: keep (in their abstract base pic-common) because + the PIT needs additional wiring by board code, depending on HPET + presence + +* pcspk: keep because of pointer property pit, and because realize + sets global pcspk_state + +* vmmouse: keep because of pointer property ps2_mouse + +* vmport: keep because realize sets global port_state + +* isa-i8259, kvm-i8259: keep (in their abstract base pic-common), + because the PICs' IRQ input lines are set up by board code, and the + wiring of the slave to the master is hard-coded in device model code +(cherry picked from pending upstream submission) + +Conflicts: + hw/i386/pc.c + hw/input/pckbd.c + hw/input/vmmouse.c + hw/intc/i8259_common.c + hw/misc/vmport.c + hw/timer/m48t59.c + hw/timer/mc146818rtc.c + +Conflicts because we don't have commit db895a1 "isa: Use realizefn +for ISADevice". Resolution is straightforward. + +We got one more ISA device to cover than upstream: + +* pvpanic : keep, so the future backport of commit a5d3f64 "hw/misc: + make pvpanic known to user" can drop it, just like it dropped + no_user upstream. Artifact of backporting out-of-order. + +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/audio/pcspk.c | 3 ++- + hw/block/fdc.c | 1 - + hw/i386/pc.c | 7 ++++++- + hw/input/pckbd.c | 1 - + hw/input/vmmouse.c | 3 ++- + hw/intc/i8259_common.c | 8 +++++++- + hw/misc/pvpanic.c | 6 +++++- + hw/misc/vmport.c | 3 ++- + hw/timer/i8254_common.c | 7 ++++++- + hw/timer/m48t59.c | 3 ++- + hw/timer/mc146818rtc.c | 3 ++- + 11 files changed, 34 insertions(+), 11 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/audio/pcspk.c | 3 ++- + hw/block/fdc.c | 1 - + hw/i386/pc.c | 7 ++++++- + hw/input/pckbd.c | 1 - + hw/input/vmmouse.c | 3 ++- + hw/intc/i8259_common.c | 8 +++++++- + hw/misc/pvpanic.c | 6 +++++- + hw/misc/vmport.c | 3 ++- + hw/timer/i8254_common.c | 7 ++++++- + hw/timer/m48t59.c | 3 ++- + hw/timer/mc146818rtc.c | 3 ++- + 11 files changed, 34 insertions(+), 11 deletions(-) + +diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c +index 9186304..c54b78d 100644 +--- a/hw/audio/pcspk.c ++++ b/hw/audio/pcspk.c +@@ -188,8 +188,9 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) + + ic->init = pcspk_initfn; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pcspk_properties; ++ /* Reason: pointer property "pit", realize sets global pcspk_state */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo pcspk_info = { +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index 1524e09..f3b5bec 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2206,7 +2206,6 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = isabus_fdc_init1; + dc->fw_name = "fdc"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = fdctrl_external_reset_isa; + dc->vmsd = &vmstate_isa_fdc; + dc->props = isa_fdc_properties; +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 0a8840a..9e5a082 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -538,9 +538,14 @@ static void port92_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = port92_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = port92_reset; + dc->vmsd = &vmstate_port92_isa; ++ /* ++ * Reason: unlike ordinary ISA devices, this one needs additional ++ * wiring: its A20 output line needs to be wired up by ++ * port92_init(). ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo port92_info = { +diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c +index 98b8b15..ed396bf 100644 +--- a/hw/input/pckbd.c ++++ b/hw/input/pckbd.c +@@ -514,7 +514,6 @@ static void i8042_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = i8042_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_kbd_isa; + } + +diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c +index c9d5131..c6059a4 100644 +--- a/hw/input/vmmouse.c ++++ b/hw/input/vmmouse.c +@@ -284,10 +284,11 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = vmmouse_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = vmmouse_reset; + dc->vmsd = &vmstate_vmmouse; + dc->props = vmmouse_properties; ++ /* Reason: pointer property "ps2_mouse" */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo vmmouse_info = { +diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c +index 70868a5..3358341 100644 +--- a/hw/intc/i8259_common.c ++++ b/hw/intc/i8259_common.c +@@ -139,9 +139,15 @@ static void pic_common_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_pic_common; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pic_properties_common; + ic->init = pic_init_common; ++ /* ++ * Reason: unlike ordinary ISA devices, the PICs need additional ++ * wiring: its IRQ input lines are set up by board code, and the ++ * wiring of the slave to the master is hard-coded in device model ++ * code. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo pic_common_type = { +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index af4a8b2..439d636 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -125,8 +125,12 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + + ic->init = pvpanic_isa_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pvpanic_isa_properties; ++ /* ++ * To be dropped in future backport of commit a5d3f64 "hw/misc: ++ * make pvpanic known to user": ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static TypeInfo pvpanic_isa_info = { +diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c +index ab7adf1..d7e1182 100644 +--- a/hw/misc/vmport.c ++++ b/hw/misc/vmport.c +@@ -156,7 +156,8 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = vmport_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ ++ /* Reason: realize sets global port_state */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo vmport_info = { +diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c +index 8f01313..d0737fa 100644 +--- a/hw/timer/i8254_common.c ++++ b/hw/timer/i8254_common.c +@@ -291,7 +291,12 @@ static void pit_common_class_init(ObjectClass *klass, void *data) + + ic->init = pit_init_common; + dc->vmsd = &vmstate_pit_common; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ ++ /* ++ * Reason: unlike ordinary ISA devices, the PIT may need to be ++ * wired to the HPET, and because of that, some wiring is always ++ * done by board code. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo pit_common_type = { +diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c +index e536bb9..d8a13fb 100644 +--- a/hw/timer/m48t59.c ++++ b/hw/timer/m48t59.c +@@ -740,9 +740,10 @@ static void m48t59_isa_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = m48t59_init_isa1; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = m48t59_reset_isa; + dc->props = m48t59_isa_properties; ++ /* Reason: needs to be wired up by m48t59_init_isa() */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo m48t59_isa_info = { +diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c +index 7a70556..432b16c 100644 +--- a/hw/timer/mc146818rtc.c ++++ b/hw/timer/mc146818rtc.c +@@ -904,9 +904,10 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = rtc_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_rtc; + dc->props = mc146818rtc_properties; ++ /* Reason: needs to be wired up by rtc_init() */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo mc146818rtc_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-iscsi-use-bdrv_new-instead-of-stack-structure.patch b/SOURCES/kvm-iscsi-use-bdrv_new-instead-of-stack-structure.patch new file mode 100644 index 0000000..0e72bda --- /dev/null +++ b/SOURCES/kvm-iscsi-use-bdrv_new-instead-of-stack-structure.patch @@ -0,0 +1,95 @@ +From 8ca7d4d814e7443da7f00696f37fb9f6f06dd668 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:58 +0100 +Subject: [PATCH 05/87] iscsi: use bdrv_new() instead of stack structure + +RH-Author: Max Reitz +Message-id: <1383604354-12743-8-git-send-email-mreitz@redhat.com> +Patchwork-id: 55307 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 07/43] iscsi: use bdrv_new() instead of stack structure +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Fam Zheng + +BZ: 1026524 + +BlockDriverState structure needs bdrv_new() to initialize refcnt, don't +allocate a local structure variable and memset to 0, becasue with coming +refcnt implementation, bdrv_unref will crash if bs->refcnt not +initialized to 1. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 13c91cb7e28b47f5c4227f7e88a1378570117704) + +Signed-off-by: Max Reitz +--- + block/iscsi.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/iscsi.c | 16 +++++++++------- + 1 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/block/iscsi.c b/block/iscsi.c +index 4ab9edc..cc2017e 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -1252,11 +1252,11 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) + { + int ret = 0; + int64_t total_size = 0; +- BlockDriverState bs; ++ BlockDriverState *bs; + IscsiLun *iscsilun = NULL; + QDict *bs_options; + +- memset(&bs, 0, sizeof(BlockDriverState)); ++ bs = bdrv_new(""); + + /* Read out options */ + while (options && options->name) { +@@ -1266,12 +1266,12 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) + options++; + } + +- bs.opaque = g_malloc0(sizeof(struct IscsiLun)); +- iscsilun = bs.opaque; ++ bs->opaque = g_malloc0(sizeof(struct IscsiLun)); ++ iscsilun = bs->opaque; + + bs_options = qdict_new(); + qdict_put(bs_options, "filename", qstring_from_str(filename)); +- ret = iscsi_open(&bs, bs_options, 0); ++ ret = iscsi_open(bs, bs_options, 0); + QDECREF(bs_options); + + if (ret != 0) { +@@ -1285,7 +1285,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) + ret = -ENODEV; + goto out; + } +- if (bs.total_sectors < total_size) { ++ if (bs->total_sectors < total_size) { + ret = -ENOSPC; + goto out; + } +@@ -1295,7 +1295,9 @@ out: + if (iscsilun->iscsi != NULL) { + iscsi_destroy_context(iscsilun->iscsi); + } +- g_free(bs.opaque); ++ g_free(bs->opaque); ++ bs->opaque = NULL; ++ bdrv_delete(bs); + return ret; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-kvmvapic-Catch-invalid-ROM-size.patch b/SOURCES/kvm-kvmvapic-Catch-invalid-ROM-size.patch new file mode 100644 index 0000000..04688b1 --- /dev/null +++ b/SOURCES/kvm-kvmvapic-Catch-invalid-ROM-size.patch @@ -0,0 +1,80 @@ +From ae31d75c7c2872dfc2172921422bf6b1c8bb6b03 Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Wed, 6 Nov 2013 02:11:01 +0100 +Subject: [PATCH 54/81] kvmvapic: Catch invalid ROM size + +RH-Author: Bandan Das +Message-id: <1383703863-4840-1-git-send-email-bsd@redhat.com> +Patchwork-id: 55471 +O-Subject: [PATCH RHEL-7.0 qemu-kvm 1/3] kvmvapic: Catch invalid ROM size +Bugzilla: 920021 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Igor Mammedov +RH-Acked-by: Alex Williamson +RH-Acked-by: Eduardo Habkost + +From: Jan Kiszka + +If not caught early, a zero-length ROM will cause a NULL-pointer access +later on in patch_hypercalls when allocating a zero-length ROM copy and +trying to read from it. + +Signed-off-by: Jan Kiszka +Signed-off-by: Paolo Bonzini +(cherry picked from commit 18e5eec4db96a00907eb588a2b803401637c7f67) + +Conflicts: + hw/i386/kvmvapic.c +--- + hw/i386/kvmvapic.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvmvapic.c | 11 +++++++++-- + 1 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index a7db94d..a2c7e8f 100644 +--- a/hw/i386/kvmvapic.c ++++ b/hw/i386/kvmvapic.c +@@ -572,7 +572,7 @@ static int patch_hypercalls(VAPICROMState *s) + * enable write access to the option ROM so that variables can be updated by + * the guest. + */ +-static void vapic_map_rom_writable(VAPICROMState *s) ++static int vapic_map_rom_writable(VAPICROMState *s) + { + hwaddr rom_paddr = s->rom_state_paddr & ROM_BLOCK_MASK; + MemoryRegionSection section; +@@ -593,6 +593,9 @@ static void vapic_map_rom_writable(VAPICROMState *s) + /* read ROM size from RAM region */ + ram = memory_region_get_ram_ptr(section.mr); + rom_size = ram[rom_paddr + 2] * ROM_BLOCK_SIZE; ++ if (rom_size == 0) { ++ return -1; ++ } + s->rom_size = rom_size; + + /* We need to round to avoid creating subpages +@@ -605,11 +608,15 @@ static void vapic_map_rom_writable(VAPICROMState *s) + rom_size); + memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000); + s->rom_mapped_writable = true; ++ ++ return 0; + } + + static int vapic_prepare(VAPICROMState *s) + { +- vapic_map_rom_writable(s); ++ if (vapic_map_rom_writable(s) < 0) { ++ return -1; ++ } + + if (patch_hypercalls(s) < 0) { + return -1; +-- +1.7.1 + diff --git a/SOURCES/kvm-kvmvapic-Clear-also-physical-ROM-address-when-enteri.patch b/SOURCES/kvm-kvmvapic-Clear-also-physical-ROM-address-when-enteri.patch new file mode 100644 index 0000000..d3a9c65 --- /dev/null +++ b/SOURCES/kvm-kvmvapic-Clear-also-physical-ROM-address-when-enteri.patch @@ -0,0 +1,55 @@ +From 9d0c4b3d52464cb38b531e610a71ff1e0f6fcf61 Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Wed, 6 Nov 2013 02:11:03 +0100 +Subject: [PATCH 56/81] kvmvapic: Clear also physical ROM address when entering INACTIVE state + +RH-Author: Bandan Das +Message-id: <1383703863-4840-3-git-send-email-bsd@redhat.com> +Patchwork-id: 55473 +O-Subject: [PATCH RHEL-7.0 qemu-kvm 3/3] kvmvapic: Clear also physical ROM address when entering INACTIVE state +Bugzilla: 920021 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Igor Mammedov +RH-Acked-by: Alex Williamson + +From: Jan Kiszka + +To avoid misinterpreting INACTIVE after migration as old qemu-kvm's +STANDBY, also clear rom_state_paddr when going back to this state. + +Signed-off-by: Jan Kiszka +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4357930b8a7d2fcff2d8121ec518117428a781e7) +--- + hw/i386/kvmvapic.c | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvmvapic.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index a96ea85..577ae64 100644 +--- a/hw/i386/kvmvapic.c ++++ b/hw/i386/kvmvapic.c +@@ -505,6 +505,7 @@ static void vapic_reset(DeviceState *dev) + VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev); + + s->state = VAPIC_INACTIVE; ++ s->rom_state_paddr = 0; + vapic_enable_tpr_reporting(false); + } + +@@ -655,6 +656,7 @@ static void vapic_write(void *opaque, hwaddr addr, uint64_t data, + } + if (vapic_prepare(s) < 0) { + s->state = VAPIC_INACTIVE; ++ s->rom_state_paddr = 0; + break; + } + break; +-- +1.7.1 + diff --git a/SOURCES/kvm-kvmvapic-Enter-inactive-state-on-hardware-reset.patch b/SOURCES/kvm-kvmvapic-Enter-inactive-state-on-hardware-reset.patch new file mode 100644 index 0000000..d5b1949 --- /dev/null +++ b/SOURCES/kvm-kvmvapic-Enter-inactive-state-on-hardware-reset.patch @@ -0,0 +1,51 @@ +From 1199c18251b039c80d66b0036e4f22bb2ce7dbd8 Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Wed, 6 Nov 2013 02:11:02 +0100 +Subject: [PATCH 55/81] kvmvapic: Enter inactive state on hardware reset + +RH-Author: Bandan Das +Message-id: <1383703863-4840-2-git-send-email-bsd@redhat.com> +Patchwork-id: 55472 +O-Subject: [PATCH RHEL-7.0 qemu-kvm 2/3] kvmvapic: Enter inactive state on hardware reset +Bugzilla: 920021 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Igor Mammedov +RH-Acked-by: Alex Williamson + +From: Jan Kiszka + +ROM layout may change after reset of devices are hotplugged, so we have +to pick up the physical address again when the ROM is initialized. This +is best achieved by resetting the state to INACTIVE. + +Signed-off-by: Jan Kiszka +Signed-off-by: Paolo Bonzini +(cherry picked from commit c056bc3f3464cfae1c94b7dd633d3ec13b13b655) +--- + hw/i386/kvmvapic.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvmvapic.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index a2c7e8f..a96ea85 100644 +--- a/hw/i386/kvmvapic.c ++++ b/hw/i386/kvmvapic.c +@@ -504,9 +504,7 @@ static void vapic_reset(DeviceState *dev) + { + VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev); + +- if (s->state == VAPIC_ACTIVE) { +- s->state = VAPIC_STANDBY; +- } ++ s->state = VAPIC_INACTIVE; + vapic_enable_tpr_reporting(false); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-libqtest-New-qtest_end-to-go-with-qtest_start.patch b/SOURCES/kvm-libqtest-New-qtest_end-to-go-with-qtest_start.patch new file mode 100644 index 0000000..f62f41f --- /dev/null +++ b/SOURCES/kvm-libqtest-New-qtest_end-to-go-with-qtest_start.patch @@ -0,0 +1,142 @@ +From ab193a7368375c73e232f3b64d9c372c70bbf52c Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:18 +0200 +Subject: [PATCH 08/14] libqtest: New qtest_end() to go with qtest_start() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-9-git-send-email-armbru@redhat.com> +Patchwork-id: 54566 +O-Subject: [PATCH 7.0 qemu-kvm 08/10] libqtest: New qtest_end() to go with qtest_start() +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Andreas Färber +Reviewed-by: Anthony Liguori +Message-id: 1371711329-9144-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 1d9358e686125c125b52529fa68baf36aa2d0d09) +--- + tests/fdc-test.c | 2 +- + tests/hd-geo-test.c | 8 ++++---- + tests/ide-test.c | 2 +- + tests/libqtest.h | 12 ++++++++++++ + 4 files changed, 18 insertions(+), 6 deletions(-) + +Signed-off-by: Michal Novotny +--- + tests/fdc-test.c | 2 +- + tests/hd-geo-test.c | 8 ++++---- + tests/ide-test.c | 2 +- + tests/libqtest.h | 12 ++++++++++++ + 4 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/tests/fdc-test.c b/tests/fdc-test.c +index 4b0301d..fd198dc 100644 +--- a/tests/fdc-test.c ++++ b/tests/fdc-test.c +@@ -556,7 +556,7 @@ int main(int argc, char **argv) + ret = g_test_run(); + + /* Cleanup */ +- qtest_quit(global_qtest); ++ qtest_end(); + unlink(test_image); + + return ret; +diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c +index 9a31e85..b72042e 100644 +--- a/tests/hd-geo-test.c ++++ b/tests/hd-geo-test.c +@@ -244,7 +244,7 @@ static void test_ide_none(void) + setup_common(argv, ARRAY_SIZE(argv)); + qtest_start(g_strjoinv(" ", argv)); + test_cmos(); +- qtest_quit(global_qtest); ++ qtest_end(); + } + + static void test_ide_mbr(bool use_device, MBRcontents mbr) +@@ -262,7 +262,7 @@ static void test_ide_mbr(bool use_device, MBRcontents mbr) + } + qtest_start(g_strjoinv(" ", argv)); + test_cmos(); +- qtest_quit(global_qtest); ++ qtest_end(); + } + + /* +@@ -334,7 +334,7 @@ static void test_ide_drive_user(const char *dev, bool trans) + g_free(opts); + qtest_start(g_strjoinv(" ", argv)); + test_cmos(); +- qtest_quit(global_qtest); ++ qtest_end(); + } + + /* +@@ -387,7 +387,7 @@ static void test_ide_drive_cd_0(void) + } + qtest_start(g_strjoinv(" ", argv)); + test_cmos(); +- qtest_quit(global_qtest); ++ qtest_end(); + } + + int main(int argc, char **argv) +diff --git a/tests/ide-test.c b/tests/ide-test.c +index 365e995..177ab00 100644 +--- a/tests/ide-test.c ++++ b/tests/ide-test.c +@@ -120,7 +120,7 @@ static void ide_test_start(const char *cmdline_fmt, ...) + + static void ide_test_quit(void) + { +- qtest_quit(global_qtest); ++ qtest_end(); + } + + static QPCIDevice *get_pci_device(uint16_t *bmdma_base) +diff --git a/tests/libqtest.h b/tests/libqtest.h +index 437bda3..0f6aade 100644 +--- a/tests/libqtest.h ++++ b/tests/libqtest.h +@@ -17,6 +17,7 @@ + #ifndef LIBQTEST_H + #define LIBQTEST_H + ++#include + #include + #include + #include +@@ -319,6 +320,17 @@ static inline QTestState *qtest_start(const char *args) + } + + /** ++ * qtest_end: ++ * ++ * Shut down the QEMU process started by qtest_start(). ++ */ ++static inline void qtest_end(void) ++{ ++ qtest_quit(global_qtest); ++ global_qtest = NULL; ++} ++ ++/** + * qmp: + * @fmt...: QMP message to send to qemu + * +-- +1.7.11.7 + diff --git a/SOURCES/kvm-libqtest-Plug-fd-and-memory-leaks-in-qtest_quit.patch b/SOURCES/kvm-libqtest-Plug-fd-and-memory-leaks-in-qtest_quit.patch new file mode 100644 index 0000000..4c39b2f --- /dev/null +++ b/SOURCES/kvm-libqtest-Plug-fd-and-memory-leaks-in-qtest_quit.patch @@ -0,0 +1,61 @@ +From 5d33e5e1bedee73ef893f1ad4141e8a613e15a84 Mon Sep 17 00:00:00 2001 +Message-Id: <5d33e5e1bedee73ef893f1ad4141e8a613e15a84.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:17 +0200 +Subject: [PATCH 07/14] libqtest: Plug fd and memory leaks in qtest_quit() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-8-git-send-email-armbru@redhat.com> +Patchwork-id: 54561 +O-Subject: [PATCH 7.0 qemu-kvm 07/10] libqtest: Plug fd and memory leaks in qtest_quit() +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Reviewed-by: Anthony Liguori +Signed-off-by: Markus Armbruster +Reviewed-by: Andreas Färber +Message-id: 1371711329-9144-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit fdd26fca3ce66863e547560fbde1a444fc5d71b7) +--- + tests/libqtest.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Michal Novotny +--- + tests/libqtest.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/libqtest.c b/tests/libqtest.c +index 879ffe9..bb82069 100644 +--- a/tests/libqtest.c ++++ b/tests/libqtest.c +@@ -171,12 +171,16 @@ void qtest_quit(QTestState *s) + waitpid(pid, &status, 0); + } + ++ close(s->fd); ++ close(s->qmp_fd); ++ g_string_free(s->rx, true); + unlink(s->pid_file); + unlink(s->socket_path); + unlink(s->qmp_socket_path); + g_free(s->pid_file); + g_free(s->socket_path); + g_free(s->qmp_socket_path); ++ g_free(s); + } + + static void socket_sendf(int fd, const char *fmt, va_list ap) +-- +1.7.11.7 + diff --git a/SOURCES/kvm-linux-headers-Update-for-KVM-VFIO-device.patch b/SOURCES/kvm-linux-headers-Update-for-KVM-VFIO-device.patch new file mode 100644 index 0000000..835fbc4 --- /dev/null +++ b/SOURCES/kvm-linux-headers-Update-for-KVM-VFIO-device.patch @@ -0,0 +1,45 @@ +From 5bf6f353b202b4b3cfcf7c570dddf0557f39480c Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 17:51:05 +0100 +Subject: [PATCH 20/25] linux-headers: Update for KVM-VFIO device + +RH-Author: Alex Williamson +Message-id: <20131105175105.19705.91817.stgit@bling.home> +Patchwork-id: 55442 +O-Subject: [RHEL7 qemu-kvm PATCH 1/2] linux-headers: Update for KVM-VFIO device +Bugzilla: 1025474 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1025474 +Upstream: Posted - http://lists.nongnu.org/archive/html/qemu-devel/2013-11/msg00090.html + +Signed-off-by: Alex Williamson +--- + linux-headers/linux/kvm.h | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + linux-headers/linux/kvm.h | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 01bf15b..e32ef4a 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -840,6 +840,10 @@ struct kvm_device_attr { + #define KVM_DEV_TYPE_FSL_MPIC_20 1 + #define KVM_DEV_TYPE_FSL_MPIC_42 2 + #define KVM_DEV_TYPE_XICS 3 ++#define KVM_DEV_TYPE_VFIO 4 ++#define KVM_DEV_VFIO_GROUP 1 ++#define KVM_DEV_VFIO_GROUP_ADD 1 ++#define KVM_DEV_VFIO_GROUP_DEL 2 + + /* + * ioctls for VM fds +-- +1.7.1 + diff --git a/SOURCES/kvm-linux-headers-Update-to-include-vfio-pci-hot-reset-s.patch b/SOURCES/kvm-linux-headers-Update-to-include-vfio-pci-hot-reset-s.patch new file mode 100644 index 0000000..2b068a1 --- /dev/null +++ b/SOURCES/kvm-linux-headers-Update-to-include-vfio-pci-hot-reset-s.patch @@ -0,0 +1,80 @@ +From 576a2f71ac459b96deb1caee171fb6ff45915688 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 17:31:05 +0100 +Subject: [PATCH 18/25] linux-headers: Update to include vfio pci hot reset support + +RH-Author: Alex Williamson +Message-id: <20131105173105.19372.39854.stgit@bling.home> +Patchwork-id: 55439 +O-Subject: [RHEL7 qemu-kvm PATCH 1/2] linux-headers: Update to include vfio pci hot reset support +Bugzilla: 1025472 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1025472 +Upstream commit: Subset of 4f265607 + +Signed-off-by: Alex Williamson +--- + linux-headers/linux/vfio.h | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + linux-headers/linux/vfio.h | 38 ++++++++++++++++++++++++++++++++++++++ + 1 files changed, 38 insertions(+), 0 deletions(-) + +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index 9e6df92..d341312 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -323,6 +323,44 @@ enum { + VFIO_PCI_NUM_IRQS + }; + ++/** ++ * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IORW(VFIO_TYPE, VFIO_BASE + 12, ++ * struct vfio_pci_hot_reset_info) ++ * ++ * Return: 0 on success, -errno on failure: ++ * -enospc = insufficient buffer, -enodev = unsupported for device. ++ */ ++struct vfio_pci_dependent_device { ++ __u32 group_id; ++ __u16 segment; ++ __u8 bus; ++ __u8 devfn; /* Use PCI_SLOT/PCI_FUNC */ ++}; ++ ++struct vfio_pci_hot_reset_info { ++ __u32 argsz; ++ __u32 flags; ++ __u32 count; ++ struct vfio_pci_dependent_device devices[]; ++}; ++ ++#define VFIO_DEVICE_GET_PCI_HOT_RESET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) ++ ++/** ++ * VFIO_DEVICE_PCI_HOT_RESET - _IOW(VFIO_TYPE, VFIO_BASE + 13, ++ * struct vfio_pci_hot_reset) ++ * ++ * Return: 0 on success, -errno on failure. ++ */ ++struct vfio_pci_hot_reset { ++ __u32 argsz; ++ __u32 flags; ++ __u32 count; ++ __s32 group_fds[]; ++}; ++ ++#define VFIO_DEVICE_PCI_HOT_RESET _IO(VFIO_TYPE, VFIO_BASE + 13) ++ + /* -------- API for Type1 VFIO IOMMU -------- */ + + /** +-- +1.7.1 + diff --git a/SOURCES/kvm-linux-headers-Update-to-v3-10-rc5.patch b/SOURCES/kvm-linux-headers-Update-to-v3-10-rc5.patch new file mode 100644 index 0000000..1cacb18 --- /dev/null +++ b/SOURCES/kvm-linux-headers-Update-to-v3-10-rc5.patch @@ -0,0 +1,472 @@ +From 203e2f3b71821558653d08bbd90ee493396ec1a6 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 6 Aug 2013 19:52:03 +0200 +Subject: linux-headers: Update to v3.10-rc5 + +RH-Author: Nigel Croxon +Message-id: <1375818724-41239-2-git-send-email-ncroxon@redhat.com> +Patchwork-id: 53016 +O-Subject: [RHEL7.0 qemu-kvm PATCH v2 1/2] linux-headers: Update to v3.10-rc5 +Bugzilla: 984604 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Alex Williamson +RH-Acked-by: Miroslav Rezanina + +From: Alexey Kardashevskiy + +This adds symbols required for PPC64 pseries platform features: +1. sPAPR live migration; +2. in-kernel XICS interrupt controller. + +Signed-off-by: Alexey Kardashevskiy +Signed-off-by: Michael Tokarev +(cherry picked from commit e098b45386a86fecc1e573d305a240a2f4aa461d) + +diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h +index 023bfeb..c1ee007 100644 +--- a/linux-headers/asm-arm/kvm.h ++++ b/linux-headers/asm-arm/kvm.h +@@ -53,12 +53,12 @@ + #define KVM_ARM_FIQ_spsr fiq_regs[7] + + struct kvm_regs { +- struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */ +- __u32 svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */ +- __u32 abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */ +- __u32 und_regs[3]; /* SP_und, LR_und, SPSR_und */ +- __u32 irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */ +- __u32 fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */ ++ struct pt_regs usr_regs; /* R0_usr - R14_usr, PC, CPSR */ ++ unsigned long svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */ ++ unsigned long abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */ ++ unsigned long und_regs[3]; /* SP_und, LR_und, SPSR_und */ ++ unsigned long irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */ ++ unsigned long fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */ + }; + + /* Supported Processor Types */ +diff --git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h +new file mode 100644 +index 0000000..3f424f5 +--- /dev/null ++++ b/linux-headers/asm-mips/kvm.h +@@ -0,0 +1,138 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. ++ * Copyright (C) 2013 Cavium, Inc. ++ * Authors: Sanjay Lal ++ */ ++ ++#ifndef __LINUX_KVM_MIPS_H ++#define __LINUX_KVM_MIPS_H ++ ++#include ++ ++/* ++ * KVM MIPS specific structures and definitions. ++ * ++ * Some parts derived from the x86 version of this file. ++ */ ++ ++/* ++ * for KVM_GET_REGS and KVM_SET_REGS ++ * ++ * If Config[AT] is zero (32-bit CPU), the register contents are ++ * stored in the lower 32-bits of the struct kvm_regs fields and sign ++ * extended to 64-bits. ++ */ ++struct kvm_regs { ++ /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ ++ __u64 gpr[32]; ++ __u64 hi; ++ __u64 lo; ++ __u64 pc; ++}; ++ ++/* ++ * for KVM_GET_FPU and KVM_SET_FPU ++ * ++ * If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs ++ * are zero filled. ++ */ ++struct kvm_fpu { ++ __u64 fpr[32]; ++ __u32 fir; ++ __u32 fccr; ++ __u32 fexr; ++ __u32 fenr; ++ __u32 fcsr; ++ __u32 pad; ++}; ++ ++ ++/* ++ * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0 ++ * registers. The id field is broken down as follows: ++ * ++ * bits[2..0] - Register 'sel' index. ++ * bits[7..3] - Register 'rd' index. ++ * bits[15..8] - Must be zero. ++ * bits[63..16] - 1 -> CP0 registers. ++ * ++ * Other sets registers may be added in the future. Each set would ++ * have its own identifier in bits[63..16]. ++ * ++ * The addr field of struct kvm_one_reg must point to an aligned ++ * 64-bit wide location. For registers that are narrower than ++ * 64-bits, the value is stored in the low order bits of the location, ++ * and sign extended to 64-bits. ++ * ++ * The registers defined in struct kvm_regs are also accessible, the ++ * id values for these are below. ++ */ ++ ++#define KVM_REG_MIPS_R0 0 ++#define KVM_REG_MIPS_R1 1 ++#define KVM_REG_MIPS_R2 2 ++#define KVM_REG_MIPS_R3 3 ++#define KVM_REG_MIPS_R4 4 ++#define KVM_REG_MIPS_R5 5 ++#define KVM_REG_MIPS_R6 6 ++#define KVM_REG_MIPS_R7 7 ++#define KVM_REG_MIPS_R8 8 ++#define KVM_REG_MIPS_R9 9 ++#define KVM_REG_MIPS_R10 10 ++#define KVM_REG_MIPS_R11 11 ++#define KVM_REG_MIPS_R12 12 ++#define KVM_REG_MIPS_R13 13 ++#define KVM_REG_MIPS_R14 14 ++#define KVM_REG_MIPS_R15 15 ++#define KVM_REG_MIPS_R16 16 ++#define KVM_REG_MIPS_R17 17 ++#define KVM_REG_MIPS_R18 18 ++#define KVM_REG_MIPS_R19 19 ++#define KVM_REG_MIPS_R20 20 ++#define KVM_REG_MIPS_R21 21 ++#define KVM_REG_MIPS_R22 22 ++#define KVM_REG_MIPS_R23 23 ++#define KVM_REG_MIPS_R24 24 ++#define KVM_REG_MIPS_R25 25 ++#define KVM_REG_MIPS_R26 26 ++#define KVM_REG_MIPS_R27 27 ++#define KVM_REG_MIPS_R28 28 ++#define KVM_REG_MIPS_R29 29 ++#define KVM_REG_MIPS_R30 30 ++#define KVM_REG_MIPS_R31 31 ++ ++#define KVM_REG_MIPS_HI 32 ++#define KVM_REG_MIPS_LO 33 ++#define KVM_REG_MIPS_PC 34 ++ ++/* ++ * KVM MIPS specific structures and definitions ++ * ++ */ ++struct kvm_debug_exit_arch { ++ __u64 epc; ++}; ++ ++/* for KVM_SET_GUEST_DEBUG */ ++struct kvm_guest_debug_arch { ++}; ++ ++/* definition of registers in kvm_run */ ++struct kvm_sync_regs { ++}; ++ ++/* dummy definition */ ++struct kvm_sregs { ++}; ++ ++struct kvm_mips_interrupt { ++ /* in */ ++ __u32 cpu; ++ __u32 irq; ++}; ++ ++#endif /* __LINUX_KVM_MIPS_H */ +diff --git a/linux-headers/asm-mips/kvm_para.h b/linux-headers/asm-mips/kvm_para.h +new file mode 100644 +index 0000000..14fab8f +--- /dev/null ++++ b/linux-headers/asm-mips/kvm_para.h +@@ -0,0 +1 @@ ++#include +diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h +index ef072b1..0fb1a6e 100644 +--- a/linux-headers/asm-powerpc/kvm.h ++++ b/linux-headers/asm-powerpc/kvm.h +@@ -25,6 +25,8 @@ + /* Select powerpc specific features in */ + #define __KVM_HAVE_SPAPR_TCE + #define __KVM_HAVE_PPC_SMT ++#define __KVM_HAVE_IRQCHIP ++#define __KVM_HAVE_IRQ_LINE + + struct kvm_regs { + __u64 pc; +@@ -272,8 +274,31 @@ struct kvm_debug_exit_arch { + + /* for KVM_SET_GUEST_DEBUG */ + struct kvm_guest_debug_arch { ++ struct { ++ /* H/W breakpoint/watchpoint address */ ++ __u64 addr; ++ /* ++ * Type denotes h/w breakpoint, read watchpoint, write ++ * watchpoint or watchpoint (both read and write). ++ */ ++#define KVMPPC_DEBUG_NONE 0x0 ++#define KVMPPC_DEBUG_BREAKPOINT (1UL << 1) ++#define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2) ++#define KVMPPC_DEBUG_WATCH_READ (1UL << 3) ++ __u32 type; ++ __u32 reserved; ++ } bp[16]; + }; + ++/* Debug related defines */ ++/* ++ * kvm_guest_debug->control is a 32 bit field. The lower 16 bits are generic ++ * and upper 16 bits are architecture specific. Architecture specific defines ++ * that ioctl is for setting hardware breakpoint or software breakpoint. ++ */ ++#define KVM_GUESTDBG_USE_SW_BP 0x00010000 ++#define KVM_GUESTDBG_USE_HW_BP 0x00020000 ++ + /* definition of registers in kvm_run */ + struct kvm_sync_regs { + }; +@@ -299,6 +324,12 @@ struct kvm_allocate_rma { + __u64 rma_size; + }; + ++/* for KVM_CAP_PPC_RTAS */ ++struct kvm_rtas_token_args { ++ char name[120]; ++ __u64 token; /* Use a token of 0 to undefine a mapping */ ++}; ++ + struct kvm_book3e_206_tlb_entry { + __u32 mas8; + __u32 mas1; +@@ -359,6 +390,26 @@ struct kvm_get_htab_header { + __u16 n_invalid; + }; + ++/* Per-vcpu XICS interrupt controller state */ ++#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c) ++ ++#define KVM_REG_PPC_ICP_CPPR_SHIFT 56 /* current proc priority */ ++#define KVM_REG_PPC_ICP_CPPR_MASK 0xff ++#define KVM_REG_PPC_ICP_XISR_SHIFT 32 /* interrupt status field */ ++#define KVM_REG_PPC_ICP_XISR_MASK 0xffffff ++#define KVM_REG_PPC_ICP_MFRR_SHIFT 24 /* pending IPI priority */ ++#define KVM_REG_PPC_ICP_MFRR_MASK 0xff ++#define KVM_REG_PPC_ICP_PPRI_SHIFT 16 /* pending irq priority */ ++#define KVM_REG_PPC_ICP_PPRI_MASK 0xff ++ ++/* Device control API: PPC-specific devices */ ++#define KVM_DEV_MPIC_GRP_MISC 1 ++#define KVM_DEV_MPIC_BASE_ADDR 0 /* 64-bit */ ++ ++#define KVM_DEV_MPIC_GRP_REGISTER 2 /* 32-bit */ ++#define KVM_DEV_MPIC_GRP_IRQ_ACTIVE 3 /* 32-bit */ ++ ++/* One-Reg API: PPC-specific registers */ + #define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1) + #define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2) + #define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3) +@@ -422,4 +473,42 @@ struct kvm_get_htab_header { + #define KVM_REG_PPC_CLEAR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88) + #define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89) + #define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a) ++ ++/* Debugging: Special instruction for software breakpoint */ ++#define KVM_REG_PPC_DEBUG_INST (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b) ++ ++/* MMU registers */ ++#define KVM_REG_PPC_MAS0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8c) ++#define KVM_REG_PPC_MAS1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8d) ++#define KVM_REG_PPC_MAS2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8e) ++#define KVM_REG_PPC_MAS7_3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8f) ++#define KVM_REG_PPC_MAS4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x90) ++#define KVM_REG_PPC_MAS6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x91) ++#define KVM_REG_PPC_MMUCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x92) ++/* ++ * TLBnCFG fields TLBnCFG_N_ENTRY and TLBnCFG_ASSOC can be changed only using ++ * KVM_CAP_SW_TLB ioctl ++ */ ++#define KVM_REG_PPC_TLB0CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x93) ++#define KVM_REG_PPC_TLB1CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94) ++#define KVM_REG_PPC_TLB2CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95) ++#define KVM_REG_PPC_TLB3CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96) ++#define KVM_REG_PPC_TLB0PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x97) ++#define KVM_REG_PPC_TLB1PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98) ++#define KVM_REG_PPC_TLB2PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99) ++#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a) ++#define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b) ++ ++/* PPC64 eXternal Interrupt Controller Specification */ ++#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */ ++ ++/* Layout of 64-bit source attribute values */ ++#define KVM_XICS_DESTINATION_SHIFT 0 ++#define KVM_XICS_DESTINATION_MASK 0xffffffffULL ++#define KVM_XICS_PRIORITY_SHIFT 32 ++#define KVM_XICS_PRIORITY_MASK 0xff ++#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40) ++#define KVM_XICS_MASKED (1ULL << 41) ++#define KVM_XICS_PENDING (1ULL << 42) ++ + #endif /* __LINUX_KVM_POWERPC_H */ +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index a65ec29..5d9a303 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -29,7 +29,6 @@ + #define __KVM_HAVE_PIT + #define __KVM_HAVE_IOAPIC + #define __KVM_HAVE_IRQ_LINE +-#define __KVM_HAVE_DEVICE_ASSIGNMENT + #define __KVM_HAVE_MSI + #define __KVM_HAVE_USER_NMI + #define __KVM_HAVE_GUEST_DEBUG +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index eb02d8a..c614070 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -561,9 +561,7 @@ struct kvm_ppc_smmu_info { + #define KVM_CAP_MP_STATE 14 + #define KVM_CAP_COALESCED_MMIO 15 + #define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */ +-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT + #define KVM_CAP_DEVICE_ASSIGNMENT 17 +-#endif + #define KVM_CAP_IOMMU 18 + #ifdef __KVM_HAVE_MSI + #define KVM_CAP_DEVICE_MSI 20 +@@ -579,13 +577,9 @@ struct kvm_ppc_smmu_info { + #ifdef __KVM_HAVE_PIT + #define KVM_CAP_REINJECT_CONTROL 24 + #endif +-#ifdef __KVM_HAVE_IOAPIC + #define KVM_CAP_IRQ_ROUTING 25 +-#endif + #define KVM_CAP_IRQ_INJECT_STATUS 26 +-#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT + #define KVM_CAP_DEVICE_DEASSIGNMENT 27 +-#endif + #ifdef __KVM_HAVE_MSIX + #define KVM_CAP_DEVICE_MSIX 28 + #endif +@@ -668,6 +662,10 @@ struct kvm_ppc_smmu_info { + #define KVM_CAP_PPC_EPR 86 + #define KVM_CAP_ARM_PSCI 87 + #define KVM_CAP_ARM_SET_DEVICE_ADDR 88 ++#define KVM_CAP_DEVICE_CTRL 89 ++#define KVM_CAP_IRQ_MPIC 90 ++#define KVM_CAP_PPC_RTAS 91 ++#define KVM_CAP_IRQ_XICS 92 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -821,6 +819,28 @@ struct kvm_arm_device_addr { + }; + + /* ++ * Device control API, available with KVM_CAP_DEVICE_CTRL ++ */ ++#define KVM_CREATE_DEVICE_TEST 1 ++ ++struct kvm_create_device { ++ __u32 type; /* in: KVM_DEV_TYPE_xxx */ ++ __u32 fd; /* out: device handle */ ++ __u32 flags; /* in: KVM_CREATE_DEVICE_xxx */ ++}; ++ ++struct kvm_device_attr { ++ __u32 flags; /* no flags currently defined */ ++ __u32 group; /* device-defined */ ++ __u64 attr; /* group-defined */ ++ __u64 addr; /* userspace address of attr data */ ++}; ++ ++#define KVM_DEV_TYPE_FSL_MPIC_20 1 ++#define KVM_DEV_TYPE_FSL_MPIC_42 2 ++#define KVM_DEV_TYPE_XICS 3 ++ ++/* + * ioctls for VM fds + */ + #define KVM_SET_MEMORY_REGION _IOW(KVMIO, 0x40, struct kvm_memory_region) +@@ -907,6 +927,16 @@ struct kvm_s390_ucas_mapping { + #define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd) + /* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */ + #define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr) ++/* Available with KVM_CAP_PPC_RTAS */ ++#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args) ++ ++/* ioctl for vm fd */ ++#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) ++ ++/* ioctls for fds returned by KVM_CREATE_DEVICE */ ++#define KVM_SET_DEVICE_ATTR _IOW(KVMIO, 0xe1, struct kvm_device_attr) ++#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr) ++#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr) + + /* + * ioctls for vcpu fds +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index e094121..7ec1864 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -319,6 +319,7 @@ enum { + VFIO_PCI_INTX_IRQ_INDEX, + VFIO_PCI_MSI_IRQ_INDEX, + VFIO_PCI_MSIX_IRQ_INDEX, ++ VFIO_PCI_ERR_IRQ_INDEX, + VFIO_PCI_NUM_IRQS + }; + +diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h +index 165a484..c656f61 100644 +--- a/linux-headers/linux/vhost.h ++++ b/linux-headers/linux/vhost.h +@@ -127,4 +127,32 @@ struct vhost_memory { + /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ + #define VHOST_NET_F_VIRTIO_NET_HDR 27 + ++/* VHOST_SCSI specific definitions */ ++ ++/* ++ * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. ++ * ++ * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + ++ * RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage ++ * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target. ++ * All the targets under vhost_wwpn can be seen and used by guset. ++ */ ++ ++#define VHOST_SCSI_ABI_VERSION 1 ++ ++struct vhost_scsi_target { ++ int abi_version; ++ char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */ ++ unsigned short vhost_tpgt; ++ unsigned short reserved; ++}; ++ ++#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) ++#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) ++/* Changing this breaks userspace. */ ++#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) ++/* Set and get the events missed flag */ ++#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32) ++#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32) ++ + #endif diff --git a/SOURCES/kvm-linux-headers-update-to-kernel-3.10.0-26.el7.patch b/SOURCES/kvm-linux-headers-update-to-kernel-3.10.0-26.el7.patch new file mode 100644 index 0000000..0fee906 --- /dev/null +++ b/SOURCES/kvm-linux-headers-update-to-kernel-3.10.0-26.el7.patch @@ -0,0 +1,194 @@ +From 4ab077cab6755cb2bad369b769a5ba077ae3264e Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Tue, 24 Sep 2013 13:08:52 +0200 +Subject: [PATCH 03/11] linux-headers: update to kernel-3.10.0-26.el7 + +RH-Author: Andrew Jones +Message-id: <1380028133-15578-2-git-send-email-drjones@redhat.com> +Patchwork-id: 54524 +O-Subject: [RHEL7.0 qemu-kvm PATCH 1/2] linux-headers: update to kernel-3.10.0-26.el7 +Bugzilla: 1008987 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Radim Krcmar +RH-Acked-by: Igor Mammedov + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1008987 + +Signed-off-by: Andrew Jones +--- + linux-headers/asm-mips/kvm.h | 81 +++++++++++++++++++--------------------- + linux-headers/asm-x86/kvm_para.h | 1 + + linux-headers/linux/kvm.h | 1 + + linux-headers/linux/kvm_para.h | 1 + + linux-headers/linux/vfio.h | 8 +++- + 5 files changed, 48 insertions(+), 44 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + linux-headers/asm-mips/kvm.h | 81 ++++++++++++++++++------------------- + linux-headers/asm-x86/kvm_para.h | 1 + + linux-headers/linux/kvm.h | 1 + + linux-headers/linux/kvm_para.h | 1 + + linux-headers/linux/vfio.h | 8 +++- + 5 files changed, 48 insertions(+), 44 deletions(-) + +diff --git a/linux-headers/asm-mips/kvm.h b/linux-headers/asm-mips/kvm.h +index 3f424f5..f09ff5a 100644 +--- a/linux-headers/asm-mips/kvm.h ++++ b/linux-headers/asm-mips/kvm.h +@@ -58,56 +58,53 @@ struct kvm_fpu { + * bits[2..0] - Register 'sel' index. + * bits[7..3] - Register 'rd' index. + * bits[15..8] - Must be zero. +- * bits[63..16] - 1 -> CP0 registers. ++ * bits[31..16] - 1 -> CP0 registers. ++ * bits[51..32] - Must be zero. ++ * bits[63..52] - As per linux/kvm.h + * + * Other sets registers may be added in the future. Each set would +- * have its own identifier in bits[63..16]. +- * +- * The addr field of struct kvm_one_reg must point to an aligned +- * 64-bit wide location. For registers that are narrower than +- * 64-bits, the value is stored in the low order bits of the location, +- * and sign extended to 64-bits. ++ * have its own identifier in bits[31..16]. + * + * The registers defined in struct kvm_regs are also accessible, the + * id values for these are below. + */ + +-#define KVM_REG_MIPS_R0 0 +-#define KVM_REG_MIPS_R1 1 +-#define KVM_REG_MIPS_R2 2 +-#define KVM_REG_MIPS_R3 3 +-#define KVM_REG_MIPS_R4 4 +-#define KVM_REG_MIPS_R5 5 +-#define KVM_REG_MIPS_R6 6 +-#define KVM_REG_MIPS_R7 7 +-#define KVM_REG_MIPS_R8 8 +-#define KVM_REG_MIPS_R9 9 +-#define KVM_REG_MIPS_R10 10 +-#define KVM_REG_MIPS_R11 11 +-#define KVM_REG_MIPS_R12 12 +-#define KVM_REG_MIPS_R13 13 +-#define KVM_REG_MIPS_R14 14 +-#define KVM_REG_MIPS_R15 15 +-#define KVM_REG_MIPS_R16 16 +-#define KVM_REG_MIPS_R17 17 +-#define KVM_REG_MIPS_R18 18 +-#define KVM_REG_MIPS_R19 19 +-#define KVM_REG_MIPS_R20 20 +-#define KVM_REG_MIPS_R21 21 +-#define KVM_REG_MIPS_R22 22 +-#define KVM_REG_MIPS_R23 23 +-#define KVM_REG_MIPS_R24 24 +-#define KVM_REG_MIPS_R25 25 +-#define KVM_REG_MIPS_R26 26 +-#define KVM_REG_MIPS_R27 27 +-#define KVM_REG_MIPS_R28 28 +-#define KVM_REG_MIPS_R29 29 +-#define KVM_REG_MIPS_R30 30 +-#define KVM_REG_MIPS_R31 31 ++#define KVM_REG_MIPS_R0 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 0) ++#define KVM_REG_MIPS_R1 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 1) ++#define KVM_REG_MIPS_R2 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 2) ++#define KVM_REG_MIPS_R3 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 3) ++#define KVM_REG_MIPS_R4 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 4) ++#define KVM_REG_MIPS_R5 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 5) ++#define KVM_REG_MIPS_R6 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 6) ++#define KVM_REG_MIPS_R7 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 7) ++#define KVM_REG_MIPS_R8 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 8) ++#define KVM_REG_MIPS_R9 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 9) ++#define KVM_REG_MIPS_R10 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 10) ++#define KVM_REG_MIPS_R11 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 11) ++#define KVM_REG_MIPS_R12 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 12) ++#define KVM_REG_MIPS_R13 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 13) ++#define KVM_REG_MIPS_R14 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 14) ++#define KVM_REG_MIPS_R15 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 15) ++#define KVM_REG_MIPS_R16 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 16) ++#define KVM_REG_MIPS_R17 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 17) ++#define KVM_REG_MIPS_R18 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 18) ++#define KVM_REG_MIPS_R19 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 19) ++#define KVM_REG_MIPS_R20 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 20) ++#define KVM_REG_MIPS_R21 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 21) ++#define KVM_REG_MIPS_R22 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 22) ++#define KVM_REG_MIPS_R23 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 23) ++#define KVM_REG_MIPS_R24 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 24) ++#define KVM_REG_MIPS_R25 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 25) ++#define KVM_REG_MIPS_R26 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 26) ++#define KVM_REG_MIPS_R27 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 27) ++#define KVM_REG_MIPS_R28 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 28) ++#define KVM_REG_MIPS_R29 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 29) ++#define KVM_REG_MIPS_R30 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 30) ++#define KVM_REG_MIPS_R31 (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 31) + +-#define KVM_REG_MIPS_HI 32 +-#define KVM_REG_MIPS_LO 33 +-#define KVM_REG_MIPS_PC 34 ++#define KVM_REG_MIPS_HI (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 32) ++#define KVM_REG_MIPS_LO (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 33) ++#define KVM_REG_MIPS_PC (KVM_REG_MIPS | KVM_REG_SIZE_U64 | 34) + + /* + * KVM MIPS specific structures and definitions +diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h +index a1c3d72..e41c5c1 100644 +--- a/linux-headers/asm-x86/kvm_para.h ++++ b/linux-headers/asm-x86/kvm_para.h +@@ -23,6 +23,7 @@ + #define KVM_FEATURE_ASYNC_PF 4 + #define KVM_FEATURE_STEAL_TIME 5 + #define KVM_FEATURE_PV_EOI 6 ++#define KVM_FEATURE_PV_UNHALT 7 + + /* The last 8 bits are used to indicate how to interpret the flags field + * in pvclock structure. If no bits are set, all flags are ignored. +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index c614070..01bf15b 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -783,6 +783,7 @@ struct kvm_dirty_tlb { + #define KVM_REG_IA64 0x3000000000000000ULL + #define KVM_REG_ARM 0x4000000000000000ULL + #define KVM_REG_S390 0x5000000000000000ULL ++#define KVM_REG_MIPS 0x7000000000000000ULL + + #define KVM_REG_SIZE_SHIFT 52 + #define KVM_REG_SIZE_MASK 0x00f0000000000000ULL +diff --git a/linux-headers/linux/kvm_para.h b/linux-headers/linux/kvm_para.h +index 7bdcf93..2dff783 100644 +--- a/linux-headers/linux/kvm_para.h ++++ b/linux-headers/linux/kvm_para.h +@@ -19,6 +19,7 @@ + #define KVM_HC_MMU_OP 2 + #define KVM_HC_FEATURES 3 + #define KVM_HC_PPC_MAP_MAGIC_PAGE 4 ++#define KVM_HC_KICK_CPU 5 + + /* + * hypercalls use architecture specific +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index 7ec1864..9e6df92 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -361,10 +361,14 @@ struct vfio_iommu_type1_dma_map { + #define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) + + /** +- * VFIO_IOMMU_UNMAP_DMA - _IOW(VFIO_TYPE, VFIO_BASE + 14, struct vfio_dma_unmap) ++ * VFIO_IOMMU_UNMAP_DMA - _IOWR(VFIO_TYPE, VFIO_BASE + 14, ++ * struct vfio_dma_unmap) + * + * Unmap IO virtual addresses using the provided struct vfio_dma_unmap. +- * Caller sets argsz. ++ * Caller sets argsz. The actual unmapped size is returned in the size ++ * field. No guarantee is made to the user that arbitrary unmaps of iova ++ * or size different from those used in the original mapping call will ++ * succeed. + */ + struct vfio_iommu_type1_dma_unmap { + __u32 argsz; +-- +1.7.1 + diff --git a/SOURCES/kvm-memory_mapping-Improve-qemu_get_guest_memory_mapping-error-reporting.patch b/SOURCES/kvm-memory_mapping-Improve-qemu_get_guest_memory_mapping-error-reporting.patch new file mode 100644 index 0000000..9fdefb1 --- /dev/null +++ b/SOURCES/kvm-memory_mapping-Improve-qemu_get_guest_memory_mapping-error-reporting.patch @@ -0,0 +1,107 @@ +From 810b9028eba23f399b2dcd22e746f99f2577150f Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:36 +0200 +Subject: memory_mapping: Improve qemu_get_guest_memory_mapping() error reporting + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-7-git-send-email-lersek@redhat.com> +Patchwork-id: 53165 +O-Subject: [RHEL-7 qemu-kvm PATCH 06/10] memory_mapping: Improve qemu_get_guest_memory_mapping() error reporting +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +From: Andreas Färber + +Pass any Error out into dump_init() and have it actually stop on errors. +Whether it is unsupported on a certain CPU can be checked by looking for +a NULL CPUClass::get_memory_mapping field. + +Reviewed-by: Luiz Capitulino +[AF: Reverted changes to CPU loops] +Signed-off-by: Andreas Färber +(cherry picked from commit 11ed09cf0753c1288a97f00138fc4534135442bb) +Signed-off-by: Laszlo Ersek + +diff --git a/dump.c b/dump.c +index 87ca12c..44a1339 100644 +--- a/dump.c ++++ b/dump.c +@@ -707,6 +707,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + { + CPUArchState *env; + int nr_cpus; ++ Error *err = NULL; + int ret; + + if (runstate_is_running()) { +@@ -757,7 +758,11 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, + /* get memory mapping */ + memory_mapping_list_init(&s->list); + if (paging) { +- qemu_get_guest_memory_mapping(&s->list); ++ qemu_get_guest_memory_mapping(&s->list, &err); ++ if (err != NULL) { ++ error_propagate(errp, err); ++ goto cleanup; ++ } + } else { + qemu_get_guest_simple_memory_mapping(&s->list); + } +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index c47e6ee..6dfb68d 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -45,13 +45,7 @@ void memory_mapping_list_free(MemoryMappingList *list); + + void memory_mapping_list_init(MemoryMappingList *list); + +-/* +- * Return value: +- * 0: success +- * -1: failed +- * -2: unsupported +- */ +-int qemu_get_guest_memory_mapping(MemoryMappingList *list); ++void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp); + + /* get guest's memory mapping without do paging(virtual address is 0). */ + void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list); +diff --git a/memory_mapping.c b/memory_mapping.c +index 9bd24ce..5634f81 100644 +--- a/memory_mapping.c ++++ b/memory_mapping.c +@@ -178,7 +178,7 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) + return NULL; + } + +-int qemu_get_guest_memory_mapping(MemoryMappingList *list) ++void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp) + { + CPUArchState *env, *first_paging_enabled_cpu; + RAMBlock *block; +@@ -190,11 +190,11 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list) + Error *err = NULL; + cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err); + if (err) { +- error_free(err); +- return -1; ++ error_propagate(errp, err); ++ return; + } + } +- return 0; ++ return; + } + + /* +@@ -206,8 +206,6 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list) + length = block->length; + create_new_memory_mapping(list, offset, offset, length); + } +- +- return 0; + } + + void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list) diff --git a/SOURCES/kvm-memory_mapping-Move-MemoryMappingList-typedef-to-qemu-typedefs-h.patch b/SOURCES/kvm-memory_mapping-Move-MemoryMappingList-typedef-to-qemu-typedefs-h.patch new file mode 100644 index 0000000..8856b7e --- /dev/null +++ b/SOURCES/kvm-memory_mapping-Move-MemoryMappingList-typedef-to-qemu-typedefs-h.patch @@ -0,0 +1,62 @@ +From 7c11083dcfe6e621276d306d18ef09b789ecb119 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Mon, 12 Aug 2013 15:59:33 +0200 +Subject: memory_mapping: Move MemoryMappingList typedef to qemu/typedefs.h + +RH-Author: Laszlo Ersek +Message-id: <1376323180-12863-4-git-send-email-lersek@redhat.com> +Patchwork-id: 53162 +O-Subject: [RHEL-7 qemu-kvm PATCH 03/10] memory_mapping: Move MemoryMappingList typedef to qemu/typedefs.h +Bugzilla: 981582 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Radim Krcmar +RH-Acked-by: Miroslav Rezanina + +From: Andreas Färber + +This will avoid issues with hwaddr and ram_addr_t when including +sysemu/memory_mapping.h for CONFIG_USER_ONLY, e.g., from qom/cpu.h. + +Signed-off-by: Andreas Färber +(cherry picked from commit 6d4d3ae77dbb756d454c2deb2ef844b0cc7bde7b) +Signed-off-by: Laszlo Ersek + +diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h +index 93aae81..1218a61 100644 +--- a/include/qemu/typedefs.h ++++ b/include/qemu/typedefs.h +@@ -22,6 +22,8 @@ typedef struct AddressSpace AddressSpace; + typedef struct MemoryRegion MemoryRegion; + typedef struct MemoryRegionSection MemoryRegionSection; + ++typedef struct MemoryMappingList MemoryMappingList; ++ + typedef struct NICInfo NICInfo; + typedef struct HCIInfo HCIInfo; + typedef struct AudioState AudioState; +diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h +index 6f01524..1f71c32 100644 +--- a/include/sysemu/memory_mapping.h ++++ b/include/sysemu/memory_mapping.h +@@ -15,6 +15,7 @@ + #define MEMORY_MAPPING_H + + #include "qemu/queue.h" ++#include "qemu/typedefs.h" + + /* The physical and virtual address in the memory mapping are contiguous. */ + typedef struct MemoryMapping { +@@ -24,11 +25,11 @@ typedef struct MemoryMapping { + QTAILQ_ENTRY(MemoryMapping) next; + } MemoryMapping; + +-typedef struct MemoryMappingList { ++struct MemoryMappingList { + unsigned int num; + MemoryMapping *last_mapping; + QTAILQ_HEAD(, MemoryMapping) head; +-} MemoryMappingList; ++}; + + int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env); + diff --git a/SOURCES/kvm-microblaze-Fix-latent-bug-with-default-DTB-lookup.patch b/SOURCES/kvm-microblaze-Fix-latent-bug-with-default-DTB-lookup.patch new file mode 100644 index 0000000..ffa8f08 --- /dev/null +++ b/SOURCES/kvm-microblaze-Fix-latent-bug-with-default-DTB-lookup.patch @@ -0,0 +1,82 @@ +From 216010b25271a2814abef68971d672632ddbd122 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:04 +0200 +Subject: [PATCH 11/28] microblaze: Fix latent bug with default DTB lookup + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-6-git-send-email-armbru@redhat.com> +Patchwork-id: 52994 +O-Subject: [PATCH 7.0 qemu-kvm 5/6] microblaze: Fix latent bug with default DTB lookup +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +microblaze_load_kernel() fails to call +qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename) when no -machine +options are given. This can't normally happen, because -machine +option kernel is mandatory for this target. Fix it anyway, by using +qemu_get_machine_opts(). + +Cc: Peter Crosthwaite +Signed-off-by: Markus Armbruster +Message-id: 1372943363-24081-6-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 7bccd9402691e712305bc3b5cc6cf2fa1cc27631) +--- + hw/microblaze/boot.c | 27 +++++++++++++-------------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/microblaze/boot.c | 27 +++++++++++++-------------- + 1 files changed, 13 insertions(+), 14 deletions(-) + +diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c +index e543d88..f03934b 100644 +--- a/hw/microblaze/boot.c ++++ b/hw/microblaze/boot.c +@@ -28,6 +28,7 @@ + #include "qemu/config-file.h" + #include "qemu-common.h" + #include "sysemu/device_tree.h" ++#include "sysemu/sysemu.h" + #include "hw/loader.h" + #include "elf.h" + +@@ -105,20 +106,18 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, + void (*machine_cpu_reset)(MicroBlazeCPU *)) + { + QemuOpts *machine_opts; +- const char *kernel_filename = NULL; +- const char *kernel_cmdline = NULL; +- +- machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); +- if (machine_opts) { +- const char *dtb_arg; +- kernel_filename = qemu_opt_get(machine_opts, "kernel"); +- kernel_cmdline = qemu_opt_get(machine_opts, "append"); +- dtb_arg = qemu_opt_get(machine_opts, "dtb"); +- if (dtb_arg) { /* Preference a -dtb argument */ +- dtb_filename = dtb_arg; +- } else { /* default to pcbios dtb as passed by machine_init */ +- dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); +- } ++ const char *kernel_filename; ++ const char *kernel_cmdline; ++ const char *dtb_arg; ++ ++ machine_opts = qemu_get_machine_opts(); ++ kernel_filename = qemu_opt_get(machine_opts, "kernel"); ++ kernel_cmdline = qemu_opt_get(machine_opts, "append"); ++ dtb_arg = qemu_opt_get(machine_opts, "dtb"); ++ if (dtb_arg) { /* Preference a -dtb argument */ ++ dtb_filename = dtb_arg; ++ } else { /* default to pcbios dtb as passed by machine_init */ ++ dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); + } + + boot_info.machine_cpu_reset = machine_cpu_reset; +-- +1.7.1 + diff --git a/SOURCES/kvm-migrate-vPMU-state.patch b/SOURCES/kvm-migrate-vPMU-state.patch new file mode 100644 index 0000000..c78d1cf --- /dev/null +++ b/SOURCES/kvm-migrate-vPMU-state.patch @@ -0,0 +1,309 @@ +From 7bb09ff3360af16599cc2cae834f676a20cdfa88 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 6 Nov 2013 08:27:29 +0100 +Subject: [PATCH 02/29] kvm: migrate vPMU state + +RH-Author: Paolo Bonzini +Message-id: <1379955972-3080-3-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54487 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 2/2] kvm: migrate vPMU state +Bugzilla: 928867 +RH-Acked-by: Juan Quintela +RH-Acked-by: Marcelo Tosatti +RH-Acked-by: Bandan Das + +Reviewed-by: Gleb Natapov +Signed-off-by: Paolo Bonzini +(cherry-picked from commit 0d89436786b02a9e7d561c4d7dc4982e4a2739db) + +Conflicts: + target-i386/machine.c + [missing 0779cae, Initialize IA32_FEATURE_CONTROL MSR in reset and migration, 2013-07-07] + +Signed-of-by: Miroslav Rezanina +--- + target-i386/cpu.h | 23 ++++++++++++ + target-i386/kvm.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++--- + target-i386/machine.c | 44 +++++++++++++++++++++++ + 3 files changed, 155 insertions(+), 5 deletions(-) + +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 74c7899..6aebc80 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -304,6 +304,8 @@ + #define MSR_TSC_ADJUST 0x0000003b + #define MSR_IA32_TSCDEADLINE 0x6e0 + ++#define MSR_P6_PERFCTR0 0xc1 ++ + #define MSR_MTRRcap 0xfe + #define MSR_MTRRcap_VCNT 8 + #define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) +@@ -317,6 +319,8 @@ + #define MSR_MCG_STATUS 0x17a + #define MSR_MCG_CTL 0x17b + ++#define MSR_P6_EVNTSEL0 0x186 ++ + #define MSR_IA32_PERF_STATUS 0x198 + + #define MSR_IA32_MISC_ENABLE 0x1a0 +@@ -342,6 +346,14 @@ + + #define MSR_MTRRdefType 0x2ff + ++#define MSR_CORE_PERF_FIXED_CTR0 0x309 ++#define MSR_CORE_PERF_FIXED_CTR1 0x30a ++#define MSR_CORE_PERF_FIXED_CTR2 0x30b ++#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x38d ++#define MSR_CORE_PERF_GLOBAL_STATUS 0x38e ++#define MSR_CORE_PERF_GLOBAL_CTRL 0x38f ++#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x390 ++ + #define MSR_MC0_CTL 0x400 + #define MSR_MC0_STATUS 0x401 + #define MSR_MC0_ADDR 0x402 +@@ -720,6 +732,9 @@ typedef struct { + #define CPU_NB_REGS CPU_NB_REGS32 + #endif + ++#define MAX_FIXED_COUNTERS 3 ++#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0) ++ + #define NB_MMU_MODES 3 + + typedef enum TPRAccess { +@@ -814,6 +829,14 @@ typedef struct CPUX86State { + uint64_t mcg_status; + uint64_t msr_ia32_misc_enable; + ++ uint64_t msr_fixed_ctr_ctrl; ++ uint64_t msr_global_ctrl; ++ uint64_t msr_global_status; ++ uint64_t msr_global_ovf_ctrl; ++ uint64_t msr_fixed_counters[MAX_FIXED_COUNTERS]; ++ uint64_t msr_gp_counters[MAX_GP_COUNTERS]; ++ uint64_t msr_gp_evtsel[MAX_GP_COUNTERS]; ++ + /* exception/interrupt handling */ + int error_code; + int exception_is_int; +diff --git a/target-i386/kvm.c b/target-i386/kvm.c +index c5a9416..4b470e4 100644 +--- a/target-i386/kvm.c ++++ b/target-i386/kvm.c +@@ -71,6 +71,9 @@ static bool has_msr_misc_enable; + static bool has_msr_kvm_steal_time; + static int lm_capable_kernel; + ++static bool has_msr_architectural_pmu; ++static uint32_t num_architectural_pmu_counters; ++ + bool kvm_allows_irq0_override(void) + { + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +@@ -579,6 +582,25 @@ int kvm_arch_init_vcpu(CPUState *cs) + break; + } + } ++ ++ if (limit >= 0x0a) { ++ uint32_t ver; ++ ++ cpu_x86_cpuid(env, 0x0a, 0, &ver, &unused, &unused, &unused); ++ if ((ver & 0xff) > 0) { ++ has_msr_architectural_pmu = true; ++ num_architectural_pmu_counters = (ver & 0xff00) >> 8; ++ ++ /* Shouldn't be more than 32, since that's the number of bits ++ * available in EBX to tell us _which_ counters are available. ++ * Play it safe. ++ */ ++ if (num_architectural_pmu_counters > MAX_GP_COUNTERS) { ++ num_architectural_pmu_counters = MAX_GP_COUNTERS; ++ } ++ } ++ } ++ + cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused); + + for (i = 0x80000000; i <= limit; i++) { +@@ -1070,7 +1092,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + struct kvm_msr_entry entries[100]; + } msr_data; + struct kvm_msr_entry *msrs = msr_data.entries; +- int n = 0; ++ int n = 0, i; + + kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); + kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); +@@ -1109,9 +1131,8 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + } + } + /* +- * The following paravirtual MSRs have side effects on the guest or are +- * too heavy for normal writeback. Limit them to reset or full state +- * updates. ++ * The following MSRs have side effects on the guest or are too heavy ++ * for normal writeback. Limit them to reset or full state updates. + */ + if (level >= KVM_PUT_RESET_STATE) { + kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, +@@ -1129,6 +1150,33 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME, + env->steal_time_msr); + } ++ if (has_msr_architectural_pmu) { ++ /* Stop the counter. */ ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, 0); ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, 0); ++ ++ /* Set the counter values. */ ++ for (i = 0; i < MAX_FIXED_COUNTERS; i++) { ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR0 + i, ++ env->msr_fixed_counters[i]); ++ } ++ for (i = 0; i < num_architectural_pmu_counters; i++) { ++ kvm_msr_entry_set(&msrs[n++], MSR_P6_PERFCTR0 + i, ++ env->msr_gp_counters[i]); ++ kvm_msr_entry_set(&msrs[n++], MSR_P6_EVNTSEL0 + i, ++ env->msr_gp_evtsel[i]); ++ } ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_STATUS, ++ env->msr_global_status); ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_OVF_CTRL, ++ env->msr_global_ovf_ctrl); ++ ++ /* Now start the PMU. */ ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, ++ env->msr_fixed_ctr_ctrl); ++ kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, ++ env->msr_global_ctrl); ++ } + if (hyperv_hypercall_available()) { + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0); + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0); +@@ -1385,6 +1433,19 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_kvm_steal_time) { + msrs[n++].index = MSR_KVM_STEAL_TIME; + } ++ if (has_msr_architectural_pmu) { ++ msrs[n++].index = MSR_CORE_PERF_FIXED_CTR_CTRL; ++ msrs[n++].index = MSR_CORE_PERF_GLOBAL_CTRL; ++ msrs[n++].index = MSR_CORE_PERF_GLOBAL_STATUS; ++ msrs[n++].index = MSR_CORE_PERF_GLOBAL_OVF_CTRL; ++ for (i = 0; i < MAX_FIXED_COUNTERS; i++) { ++ msrs[n++].index = MSR_CORE_PERF_FIXED_CTR0 + i; ++ } ++ for (i = 0; i < num_architectural_pmu_counters; i++) { ++ msrs[n++].index = MSR_P6_PERFCTR0 + i; ++ msrs[n++].index = MSR_P6_EVNTSEL0 + i; ++ } ++ } + + if (env->mcg_cap) { + msrs[n++].index = MSR_MCG_STATUS; +@@ -1401,7 +1462,8 @@ static int kvm_get_msrs(X86CPU *cpu) + } + + for (i = 0; i < ret; i++) { +- switch (msrs[i].index) { ++ uint32_t index = msrs[i].index; ++ switch (index) { + case MSR_IA32_SYSENTER_CS: + env->sysenter_cs = msrs[i].data; + break; +@@ -1473,6 +1535,27 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_KVM_STEAL_TIME: + env->steal_time_msr = msrs[i].data; + break; ++ case MSR_CORE_PERF_FIXED_CTR_CTRL: ++ env->msr_fixed_ctr_ctrl = msrs[i].data; ++ break; ++ case MSR_CORE_PERF_GLOBAL_CTRL: ++ env->msr_global_ctrl = msrs[i].data; ++ break; ++ case MSR_CORE_PERF_GLOBAL_STATUS: ++ env->msr_global_status = msrs[i].data; ++ break; ++ case MSR_CORE_PERF_GLOBAL_OVF_CTRL: ++ env->msr_global_ovf_ctrl = msrs[i].data; ++ break; ++ case MSR_CORE_PERF_FIXED_CTR0 ... MSR_CORE_PERF_FIXED_CTR0 + MAX_FIXED_COUNTERS - 1: ++ env->msr_fixed_counters[index - MSR_CORE_PERF_FIXED_CTR0] = msrs[i].data; ++ break; ++ case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR0 + MAX_GP_COUNTERS - 1: ++ env->msr_gp_counters[index - MSR_P6_PERFCTR0] = msrs[i].data; ++ break; ++ case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL0 + MAX_GP_COUNTERS - 1: ++ env->msr_gp_evtsel[index - MSR_P6_EVNTSEL0] = msrs[i].data; ++ break; + } + } + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 4f30347..08b4ed3 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -465,6 +465,47 @@ static const VMStateDescription vmstate_xsave ={ + } + }; + ++static bool pmu_enable_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ int i; ++ ++ if (env->msr_fixed_ctr_ctrl || env->msr_global_ctrl || ++ env->msr_global_status || env->msr_global_ovf_ctrl) { ++ return true; ++ } ++ for (i = 0; i < MAX_FIXED_COUNTERS; i++) { ++ if (env->msr_fixed_counters[i]) { ++ return true; ++ } ++ } ++ for (i = 0; i < MAX_GP_COUNTERS; i++) { ++ if (env->msr_gp_counters[i] || env->msr_gp_evtsel[i]) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static const VMStateDescription vmstate_msr_architectural_pmu = { ++ .name = "cpu/msr_architectural_pmu", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField []) { ++ VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU), ++ VMSTATE_UINT64(env.msr_global_ctrl, X86CPU), ++ VMSTATE_UINT64(env.msr_global_status, X86CPU), ++ VMSTATE_UINT64(env.msr_global_ovf_ctrl, X86CPU), ++ VMSTATE_UINT64_ARRAY(env.msr_fixed_counters, X86CPU, MAX_FIXED_COUNTERS), ++ VMSTATE_UINT64_ARRAY(env.msr_gp_counters, X86CPU, MAX_GP_COUNTERS), ++ VMSTATE_UINT64_ARRAY(env.msr_gp_evtsel, X86CPU, MAX_GP_COUNTERS), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + const VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -594,6 +635,9 @@ const VMStateDescription vmstate_x86_cpu = { + .vmsd = &vmstate_xsave, + .needed = vmstate_xsave_needed, + }, { ++ .vmsd = &vmstate_msr_architectural_pmu, ++ .needed = pmu_enable_needed, ++ }, { + /* empty */ + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-migration-add-autoconvergence-documentation.patch b/SOURCES/kvm-migration-add-autoconvergence-documentation.patch new file mode 100644 index 0000000..78e8eb7 --- /dev/null +++ b/SOURCES/kvm-migration-add-autoconvergence-documentation.patch @@ -0,0 +1,47 @@ +From 8fae371c482877d1f46bd19c5ae97d63dc707148 Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:12 +0200 +Subject: [PATCH 17/25] migration: add autoconvergence documentation + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-8-git-send-email-owasserm@redhat.com> +Patchwork-id: 54803 +O-Subject: [RHEL7.0 qemu-kvm v2 07/10] migration: add autoconvergence documentation +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Juan Quintela + +This hunk got lost during merge. It is documentation. + +Spotted-by: Peter Lieven +Signed-off-by: Juan Quintela +(cherry picked from commit 9781c3716a4b529a2af64502926a57c11e69e6ca) +--- + qapi-schema.json | 3 +++ + 1 file changed, 3 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index a717fbf..ffe0ed1 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -611,6 +611,9 @@ + # to enable the capability on the source VM. The feature is disabled by + # default. (since 1.6) + # ++# @auto-converge: If enabled, QEMU will automatically throttle down the guest ++# to speed up convergence of RAM migration. (since 1.6) ++# + # Since: 1.2 + ## + { 'enum': 'MigrationCapability', +-- +1.7.1 + diff --git a/SOURCES/kvm-migration-disable-live-block-migration-b-i-for-rhel-.patch b/SOURCES/kvm-migration-disable-live-block-migration-b-i-for-rhel-.patch new file mode 100644 index 0000000..70f15c1 --- /dev/null +++ b/SOURCES/kvm-migration-disable-live-block-migration-b-i-for-rhel-.patch @@ -0,0 +1,104 @@ +From 291074de7615878e297df1e821f9a71ce5dd784a Mon Sep 17 00:00:00 2001 +From: Jeff Cody +Date: Thu, 7 Nov 2013 07:33:12 +0100 +Subject: [PATCH 59/81] migration: disable live block migration (-b/-i) for rhel and rhev + +RH-Author: Jeff Cody +Message-id: <696b8063664491b1d1799450b4498927c2ae9908.1383712781.git.jcody@redhat.com> +Patchwork-id: 55480 +O-Subject: [RHEL7 qemu-kvm PATCH 3/3] migration: disable live block migration (-b/-i) for rhel and rhev +Bugzilla: 1022392 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Eric Blake +RH-Acked-by: Kevin Wolf + +This disables live block migration (both -b and -i options) for both +the RHEL and RHEV versions of qemu-kvm. Rather than delete the options +from the QAPI/QMP commands (which would be unfriendly to libvirt), the +options return a QMP error of unsupported ("this feature or command is +not currently supported"). + +A configure option to enable/disable this is set, which defaults to the +command options being disabled. Just to be safe, the rpm spec template +explicitly disables it as well. + +Signed-off-by: Jeff Cody +Signed-off-by: Miroslav Rezanina +--- + configure | 12 ++++++++++++ + migration.c | 7 +++++++ + redhat/qemu-kvm.spec.template | 1 + + 3 files changed, 20 insertions(+), 0 deletions(-) + +diff --git a/configure b/configure +index 9260d3c..d658434 100755 +--- a/configure ++++ b/configure +@@ -241,6 +241,7 @@ gtkabi="2.0" + tpm="no" + libssh2="" + live_block_ops="yes" ++live_block_migration="no" + + # parse CC options first + for opt do +@@ -932,6 +933,10 @@ for opt do + ;; + --enable-live-block-ops) live_block_ops="yes" + ;; ++ --disable-live-block-migration) live_block_migration="no" ++ ;; ++ --enable-live-block-migration) live_block_migration="yes" ++ ;; + *) echo "ERROR: unknown option $opt"; show_help="yes" + ;; + esac +@@ -1202,6 +1207,8 @@ echo " --disable-libssh2 disable ssh block device support" + echo " --enable-libssh2 enable ssh block device support" + echo " --disable-live-block-ops disable live block operations support" + echo " --enable-live-block-ops enable live block operations support" ++echo " --disable-live-block-migration disable live block migration" ++echo " --enable-live-block-migration enable live block migration" + echo "" + echo "NOTE: The object files are built at the place where configure is launched" + exit 1 +@@ -3564,6 +3571,7 @@ echo "libssh2 support $libssh2" + echo "TPM passthrough $tpm_passthrough" + echo "QOM debugging $qom_cast_debug" + echo "Live block operations $live_block_ops" ++echo "Live block migration $live_block_migration" + + if test "$sdl_too_old" = "yes"; then + echo "-> Your SDL version is too old - please upgrade to have SDL support" +@@ -3952,6 +3960,10 @@ if test "$live_block_ops" = "yes" ; then + echo "CONFIG_LIVE_BLOCK_OPS=y" >> $config_host_mak + fi + ++if test "$live_block_migration" = "yes" ; then ++ echo "CONFIG_LIVE_BLOCK_MIGRATION=y" >> $config_host_mak ++fi ++ + # USB host support + if test "$libusb" = "yes"; then + echo "HOST_USB=libusb legacy" >> $config_host_mak +diff --git a/migration.c b/migration.c +index 6b87272..46c633a 100644 +--- a/migration.c ++++ b/migration.c +@@ -388,6 +388,13 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, + params.blk = has_blk && blk; + params.shared = has_inc && inc; + ++#ifndef CONFIG_LIVE_BLOCK_MIGRATION ++ if (params.blk || params.shared) { ++ error_set(errp, QERR_UNSUPPORTED); ++ return; ++ } ++#endif ++ + if (s->state == MIG_STATE_ACTIVE) { + error_set(errp, QERR_MIGRATION_ACTIVE); + return; +-- +1.7.1 + diff --git a/SOURCES/kvm-migration-don-t-use-uninitialized-variables.patch b/SOURCES/kvm-migration-don-t-use-uninitialized-variables.patch new file mode 100644 index 0000000..3794fd3 --- /dev/null +++ b/SOURCES/kvm-migration-don-t-use-uninitialized-variables.patch @@ -0,0 +1,51 @@ +From 2fb2657213334c34748f1353767654208f76ef94 Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:14 +0200 +Subject: [PATCH 19/25] migration: don't use uninitialized variables + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-10-git-send-email-owasserm@redhat.com> +Patchwork-id: 54805 +O-Subject: [RHEL7.0 qemu-kvm v2 09/10] migration: don't use uninitialized variables +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Pawit Pornkitprasan + +The qmp_migrate method uses the 'blk' and 'inc' parameter without +checking if they're valid or not (they may be uninitialized if +command is received via QMP) + +Signed-off-by: Pawit Pornkitprasan +Reviewed-by: Eric Blake +Signed-off-by: Luiz Capitulino +(cherry picked from commit 8c0426aed1d2279845e6a2c3355da8b5d9926cb6) +--- + migration.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + migration.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/migration.c b/migration.c +index d69ac97..6b87272 100644 +--- a/migration.c ++++ b/migration.c +@@ -385,8 +385,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, + MigrationParams params; + const char *p; + +- params.blk = blk; +- params.shared = inc; ++ params.blk = has_blk && blk; ++ params.shared = has_inc && inc; + + if (s->state == MIG_STATE_ACTIVE) { + error_set(errp, QERR_MIGRATION_ACTIVE); +-- +1.7.1 + diff --git a/SOURCES/kvm-migration-notify-migration-state-before-starting-thread.patch b/SOURCES/kvm-migration-notify-migration-state-before-starting-thread.patch new file mode 100644 index 0000000..99ffb10 --- /dev/null +++ b/SOURCES/kvm-migration-notify-migration-state-before-starting-thread.patch @@ -0,0 +1,48 @@ +From cfa096accd51fe9b1dfa9693ce6f4628a4e83fe6 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 13 Aug 2013 09:06:35 +0200 +Subject: migration: notify migration state before starting thread + +RH-Author: Stefan Hajnoczi +Message-id: <1376384797-4701-5-git-send-email-stefanha@redhat.com> +Patchwork-id: 53209 +O-Subject: [PATCH v2 4/6] migration: notify migration state before starting thread +Bugzilla: 995030 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Kevin Wolf +RH-Acked-by: Michael S. Tsirkin + +The migration thread runs outside the QEMU global mutex when possible. +Therefore we must notify migration state change *before* starting the +migration thread. + +This allows registered listeners to act before live migration iterations +begin. Therefore they can get into a state that allows for live +migration. When the migration thread starts everything will be ready. + +Without this patch there is a race condition during migration setup, +depending on whether the migration thread has already transitioned from +SETUP to ACTIVE state. + +Acked-by: Paolo Bonzini +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 9287ac271d83166f99e050a0e0a4ebd462f7eb2b) + +Signed-off-by: Stefan Hajnoczi + +diff --git a/migration.c b/migration.c +index 6e29f72..177fc22 100644 +--- a/migration.c ++++ b/migration.c +@@ -601,7 +601,9 @@ void migrate_fd_connect(MigrationState *s) + qemu_file_set_rate_limit(s->file, + s->bandwidth_limit / XFER_LIMIT_RATIO); + ++ /* Notify before starting migration thread */ ++ notifier_list_notify(&migration_state_notifiers, s); ++ + qemu_thread_create(&s->thread, migration_thread, s, + QEMU_THREAD_JOINABLE); +- notifier_list_notify(&migration_state_notifiers, s); + } diff --git a/SOURCES/kvm-migration-send-total-time-in-QMP-at-completed-stage.patch b/SOURCES/kvm-migration-send-total-time-in-QMP-at-completed-stage.patch new file mode 100644 index 0000000..e7e60ef --- /dev/null +++ b/SOURCES/kvm-migration-send-total-time-in-QMP-at-completed-stage.patch @@ -0,0 +1,48 @@ +From b6ec816cb5032ff419a4c30f1a65ffb51250d52d Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:13 +0200 +Subject: [PATCH 18/25] migration: send total time in QMP at "completed" stage + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-9-git-send-email-owasserm@redhat.com> +Patchwork-id: 54804 +O-Subject: [RHEL7.0 qemu-kvm v2 08/10] migration: send total time in QMP at "completed" stage +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: Pawit Pornkitprasan + +The "completed" stage sets total_time but not has_total_time and +thus it is not sent via QMP reply (but sent via HMP nevertheless) + +Signed-off-by: Pawit Pornkitprasan +Reviewed-by: Eric Blake +Reviewed-by: Orit Wasserman +Signed-off-by: Luiz Capitulino +(cherry picked from commit 00c14997cb95bf3e6c18c2264ef5e10642d89b3a) +--- + migration.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + migration.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/migration.c b/migration.c +index cc0e649..d69ac97 100644 +--- a/migration.c ++++ b/migration.c +@@ -217,6 +217,7 @@ MigrationInfo *qmp_query_migrate(Error **errp) + + info->has_status = true; + info->status = g_strdup("completed"); ++ info->has_total_time = true; + info->total_time = s->total_time; + info->has_downtime = true; + info->downtime = s->downtime; +-- +1.7.1 + diff --git a/SOURCES/kvm-misc-Add-auto-converge-migration-capability.patch b/SOURCES/kvm-misc-Add-auto-converge-migration-capability.patch new file mode 100644 index 0000000..2b08630 --- /dev/null +++ b/SOURCES/kvm-misc-Add-auto-converge-migration-capability.patch @@ -0,0 +1,86 @@ +From b436b4fc9924560ab70e2ab45361de7054ddb052 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 31 Jul 2013 15:12:18 +0200 +Subject: Add 'auto-converge' migration capability + +RH-Author: Nigel Croxon +Message-id: <1375283539-18714-3-git-send-email-ncroxon@redhat.com> +Patchwork-id: 52875 +O-Subject: [RHEL7 PATCH 2/3] Add 'auto-converge' migration capability +Bugzilla: 985958 +RH-Acked-by: Orit Wasserman +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +Bugzilla: 985958 - Throttle-down guest to help with live migration convergence (backport to RHEL7.0) +https://bugzilla.redhat.com/show_bug.cgi?id=985958 + +Backported from the following upstream commit with 1 merge conflict. +Hand merge qapi-schema.json. + +commit bde1e2ec2176c363c1783bf8887b6b1beb08dfee +Author: Chegu Vinod +Date: Mon Jun 24 03:49:42 2013 -0600 + + Add 'auto-converge' migration capability + + The auto-converge migration capability allows the user to specify if they + choose live migration seqeunce to automatically detect and force convergence. + + Signed-off-by: Chegu Vinod + Reviewed-by: Paolo Bonzini + Reviewed-by: Eric Blake + Signed-off-by: Juan Quintela + +diff --git a/include/migration/migration.h b/include/migration/migration.h +index e2acec6..1fc2666 100644 +--- a/include/migration/migration.h ++++ b/include/migration/migration.h +@@ -119,6 +119,8 @@ void migrate_add_blocker(Error *reason); + */ + void migrate_del_blocker(Error *reason); + ++bool migrate_auto_converge(void); ++ + int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, + uint8_t *dst, int dlen); + int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen); +diff --git a/migration.c b/migration.c +index bfbc345..6e29f72 100644 +--- a/migration.c ++++ b/migration.c +@@ -474,6 +474,15 @@ void qmp_migrate_set_downtime(double value, Error **errp) + max_downtime = (uint64_t)value; + } + ++bool migrate_auto_converge(void) ++{ ++ MigrationState *s; ++ ++ s = migrate_get_current(); ++ ++ return s->enabled_capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE]; ++} ++ + int migrate_use_xbzrle(void) + { + MigrationState *s; +diff --git a/qapi-schema.json b/qapi-schema.json +index 9302e7d..537f1d1 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -602,10 +602,13 @@ + # This feature allows us to minimize migration traffic for certain work + # loads, by sending compressed difference of the pages + # ++# @auto-converge: If enabled, QEMU will automatically throttle down the guest ++# to speed up convergence of RAM migration. (since 1.6) ++# + # Since: 1.2 + ## + { 'enum': 'MigrationCapability', +- 'data': ['xbzrle'] } ++ 'data': ['xbzrle', 'auto-converge'] } + + ## + # @MigrationCapabilityStatus diff --git a/SOURCES/kvm-misc-Disable-EFI-enabled-roms.patch b/SOURCES/kvm-misc-Disable-EFI-enabled-roms.patch new file mode 100644 index 0000000..506674f --- /dev/null +++ b/SOURCES/kvm-misc-Disable-EFI-enabled-roms.patch @@ -0,0 +1,117 @@ +From caebed054838182932ee76d0dda6a8478ccf3760 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 1 Aug 2013 10:02:33 +0200 +Subject: Disable EFI-enabled roms + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 52889 +O-Subject: [RHEL7 qemu-kvm PATCH v2] Disable EFI-enabled roms +Bugzilla: 962563 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny + +Bugzilla: 962563 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6115956 + +We do not ship OVMF and cannot support them therefor ipxe do not include UEFI +driver. Remove usage of EFI-enabled roms + +Note: Compatibility code is not reverted to allow cleaner backports in future. + +v2: + - rebased to 1.5.2-2 + - removing compat_props +Signed-off-by: Miroslav Rezanina + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 23002ce..e1bedec 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -812,18 +812,6 @@ static QEMUMachine pc_machine_rhel700 = { + /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ + .value = stringify(0xFFFFFFFF),\ + },{\ +- .driver = "e1000",\ +- .property = "romfile",\ +- .value = "pxe-e1000.rom",\ +- },{\ +- .driver = "rtl8139",\ +- .property = "romfile",\ +- .value = "pxe-rtl8139.rom",\ +- },{\ +- .driver = "virtio-net-pci",\ +- .property = "romfile",\ +- .value = "pxe-virtio.rom",\ +- },{\ + .driver = "486-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(0),\ +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index 661b461..76df2f3 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1388,7 +1388,7 @@ static void e1000_class_init(ObjectClass *klass, void *data) + + k->init = pci_e1000_init; + k->exit = pci_e1000_uninit; +- k->romfile = "efi-e1000.rom"; ++ k->romfile = "pxe-e1000.rom"; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = E1000_DEVID; + k->revision = 0x03; +diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c +index 33ee03e..94d6110 100644 +--- a/hw/net/ne2000.c ++++ b/hw/net/ne2000.c +@@ -766,7 +766,7 @@ static void ne2000_class_init(ObjectClass *klass, void *data) + + k->init = pci_ne2000_init; + k->exit = pci_ne2000_exit; +- k->romfile = "efi-ne2k_pci.rom", ++ k->romfile = "pxe-ne2k_pci.rom", + k->vendor_id = PCI_VENDOR_ID_REALTEK; + k->device_id = PCI_DEVICE_ID_REALTEK_8029; + k->class_id = PCI_CLASS_NETWORK_ETHERNET; +diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c +index 9df2b87..e07f388 100644 +--- a/hw/net/pcnet-pci.c ++++ b/hw/net/pcnet-pci.c +@@ -351,7 +351,7 @@ static void pcnet_class_init(ObjectClass *klass, void *data) + + k->init = pci_pcnet_init; + k->exit = pci_pcnet_uninit; +- k->romfile = "efi-pcnet.rom", ++ k->romfile = "pxe-pcnet.rom", + k->vendor_id = PCI_VENDOR_ID_AMD; + k->device_id = PCI_DEVICE_ID_AMD_LANCE; + k->revision = 0x10; +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 7993f9f..1e5a679 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -3533,7 +3533,7 @@ static void rtl8139_class_init(ObjectClass *klass, void *data) + + k->init = pci_rtl8139_init; + k->exit = pci_rtl8139_uninit; +- k->romfile = "efi-rtl8139.rom"; ++ k->romfile = "pxe-rtl8139.rom"; + k->vendor_id = PCI_VENDOR_ID_REALTEK; + k->device_id = PCI_DEVICE_ID_REALTEK_8139; + k->revision = RTL8139_PCI_REVID; /* >=0x20 is for 8139C+ */ +diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c +index 161ade3..d82f6ff 100644 +--- a/hw/virtio/virtio-pci.c ++++ b/hw/virtio/virtio-pci.c +@@ -1418,7 +1418,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data) + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); + +- k->romfile = "efi-virtio.rom"; ++ k->romfile = "pxe-virtio.rom"; + k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + k->device_id = PCI_DEVICE_ID_VIRTIO_NET; + k->revision = VIRTIO_PCI_ABI_VERSION; +diff --git a/redhat/qemu-kvm.spec.template b/redhat/qemu-kvm.spec.template +index d1fb86f..95a1660 100644 diff --git a/SOURCES/kvm-misc-Force-auto-convegence-of-live-migration.patch b/SOURCES/kvm-misc-Force-auto-convegence-of-live-migration.patch new file mode 100644 index 0000000..82fcd3f --- /dev/null +++ b/SOURCES/kvm-misc-Force-auto-convegence-of-live-migration.patch @@ -0,0 +1,207 @@ +From b0acf414158ed72f3f2ac7550839af74b0530c8e Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 31 Jul 2013 15:12:19 +0200 +Subject: Force auto-convegence of live migration + +RH-Author: Nigel Croxon +Message-id: <1375283539-18714-4-git-send-email-ncroxon@redhat.com> +Patchwork-id: 52873 +O-Subject: [RHEL7 PATCH 3/3] Force auto-convegence of live migration +Bugzilla: 985958 +RH-Acked-by: Orit Wasserman +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +Bugzilla: 985958 - Throttle-down guest to help with live migration convergence (backport to RHEL7.0) +https://bugzilla.redhat.com/show_bug.cgi?id=985958 + +Backported from the following upstream commit: + +commit 7ca1dfad952d8a8655b32e78623edcc38a51b14a +Author: Chegu Vinod +Date: Mon Jun 24 03:47:39 2013 -0600 + + Force auto-convegence of live migration + + If a user chooses to turn on the auto-converge migration capability + these changes detect the lack of convergence and throttle down the + guest. i.e. force the VCPUs out of the guest for some duration + and let the migration thread catchup and help converge. + + Verified the convergence using the following : + - Java Warehouse workload running on a 20VCPU/256G guest(~80% busy) + - OLTP like workload running on a 80VCPU/512G guest (~80% busy) + + Sample results with Java warehouse workload : (migrate speed set to 20Gb and + migrate downtime set to 4seconds). + + (qemu) info migrate + capabilities: xbzrle: off auto-converge: off <---- + Migration status: active + total time: 1487503 milliseconds + expected downtime: 519 milliseconds + transferred ram: 383749347 kbytes + remaining ram: 2753372 kbytes + total ram: 268444224 kbytes + duplicate: 65461532 pages + skipped: 64901568 pages + normal: 95750218 pages + normal bytes: 383000872 kbytes + dirty pages rate: 67551 pages + + --- + + (qemu) info migrate + capabilities: xbzrle: off auto-converge: on <---- + Migration status: completed + total time: 241161 milliseconds + downtime: 6373 milliseconds + transferred ram: 28235307 kbytes + remaining ram: 0 kbytes + total ram: 268444224 kbytes + duplicate: 64946416 pages + skipped: 64903523 pages + normal: 7044971 pages + normal bytes: 28179884 kbytes + + Signed-off-by: Chegu Vinod + Signed-off-by: Juan Quintela + +diff --git a/arch_init.c b/arch_init.c +index 522caeb..d7a5d7c 100644 +--- a/arch_init.c ++++ b/arch_init.c +@@ -104,6 +104,9 @@ int graphic_depth = 15; + #endif + + const uint32_t arch_type = QEMU_ARCH; ++static bool mig_throttle_on; ++static int dirty_rate_high_cnt; ++static void check_guest_throttling(void); + + /***********************************************************/ + /* ram save/restore */ +@@ -378,8 +381,14 @@ static void migration_bitmap_sync(void) + uint64_t num_dirty_pages_init = migration_dirty_pages; + MigrationState *s = migrate_get_current(); + static int64_t start_time; ++ static int64_t bytes_xfer_prev; + static int64_t num_dirty_pages_period; + int64_t end_time; ++ int64_t bytes_xfer_now; ++ ++ if (!bytes_xfer_prev) { ++ bytes_xfer_prev = ram_bytes_transferred(); ++ } + + if (!start_time) { + start_time = qemu_get_clock_ms(rt_clock); +@@ -404,6 +413,25 @@ static void migration_bitmap_sync(void) + + /* more than 1 second = 1000 millisecons */ + if (end_time > start_time + 1000) { ++ if (migrate_auto_converge()) { ++ /* The following detection logic can be refined later. For now: ++ Check to see if the dirtied bytes is 50% more than the approx. ++ amount of bytes that just got transferred since the last time we ++ were in this routine. If that happens >N times (for now N==4) ++ we turn on the throttle down logic */ ++ bytes_xfer_now = ram_bytes_transferred(); ++ if (s->dirty_pages_rate && ++ (num_dirty_pages_period * TARGET_PAGE_SIZE > ++ (bytes_xfer_now - bytes_xfer_prev)/2) && ++ (dirty_rate_high_cnt++ > 4)) { ++ trace_migration_throttle(); ++ mig_throttle_on = true; ++ dirty_rate_high_cnt = 0; ++ } ++ bytes_xfer_prev = bytes_xfer_now; ++ } else { ++ mig_throttle_on = false; ++ } + s->dirty_pages_rate = num_dirty_pages_period * 1000 + / (end_time - start_time); + s->dirty_bytes_rate = s->dirty_pages_rate * TARGET_PAGE_SIZE; +@@ -566,6 +594,8 @@ static int ram_save_setup(QEMUFile *f, void *opaque) + migration_bitmap = bitmap_new(ram_pages); + bitmap_set(migration_bitmap, 0, ram_pages); + migration_dirty_pages = ram_pages; ++ mig_throttle_on = false; ++ dirty_rate_high_cnt = 0; + + if (migrate_use_xbzrle()) { + XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() / +@@ -628,6 +658,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) + } + total_sent += bytes_sent; + acct_info.iterations++; ++ check_guest_throttling(); + /* we want to check in the 1st loop, just in case it was the 1st time + and we had to sync the dirty bitmap. + qemu_get_clock_ns() is a bit expensive, so we only check each some +@@ -1097,3 +1128,53 @@ TargetInfo *qmp_query_target(Error **errp) + + return info; + } ++ ++/* Stub function that's gets run on the vcpu when its brought out of the ++ VM to run inside qemu via async_run_on_cpu()*/ ++static void mig_sleep_cpu(void *opq) ++{ ++ qemu_mutex_unlock_iothread(); ++ g_usleep(30*1000); ++ qemu_mutex_lock_iothread(); ++} ++ ++/* To reduce the dirty rate explicitly disallow the VCPUs from spending ++ much time in the VM. The migration thread will try to catchup. ++ Workload will experience a performance drop. ++*/ ++static void mig_throttle_cpu_down(CPUState *cpu, void *data) ++{ ++ async_run_on_cpu(cpu, mig_sleep_cpu, NULL); ++} ++ ++static void mig_throttle_guest_down(void) ++{ ++ qemu_mutex_lock_iothread(); ++ qemu_for_each_cpu(mig_throttle_cpu_down, NULL); ++ qemu_mutex_unlock_iothread(); ++} ++ ++static void check_guest_throttling(void) ++{ ++ static int64_t t0; ++ int64_t t1; ++ ++ if (!mig_throttle_on) { ++ return; ++ } ++ ++ if (!t0) { ++ t0 = qemu_get_clock_ns(rt_clock); ++ return; ++ } ++ ++ t1 = qemu_get_clock_ns(rt_clock); ++ ++ /* If it has been more than 40 ms since the last time the guest ++ * was throttled then do it again. ++ */ ++ if (40 < (t1-t0)/1000000) { ++ mig_throttle_guest_down(); ++ t0 = t1; ++ } ++} +diff --git a/trace-events b/trace-events +index 9c73931..7cd335d 100644 +--- a/trace-events ++++ b/trace-events +@@ -1031,6 +1031,7 @@ savevm_section_end(unsigned int section_id) "section_id %u" + # arch_init.c + migration_bitmap_sync_start(void) "" + migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64"" ++migration_throttle(void) "" + + # hw/qxl.c + disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d" diff --git a/SOURCES/kvm-misc-Introduce-async_run_on_cpu.patch b/SOURCES/kvm-misc-Introduce-async_run_on_cpu.patch new file mode 100644 index 0000000..6d08c2c --- /dev/null +++ b/SOURCES/kvm-misc-Introduce-async_run_on_cpu.patch @@ -0,0 +1,120 @@ +From 1666ea1986c2fdce3bc27aa96ae6bf3a632dbc99 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 31 Jul 2013 15:12:17 +0200 +Subject: Introduce async_run_on_cpu + +RH-Author: Nigel Croxon +Message-id: <1375283539-18714-2-git-send-email-ncroxon@redhat.com> +Patchwork-id: 52874 +O-Subject: [RHEL7 PATCH 1/3] Introduce async_run_on_cpu +Bugzilla: 985958 +RH-Acked-by: Orit Wasserman +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +Bugzilla: 985958 - Throttle-down guest to help with live migration convergence (backport to RHEL7.0) +https://bugzilla.redhat.com/show_bug.cgi?id=985958 + +Backported from the following upstream commit: + +commit 3c02270db980007424d797506301826310ce2db4 +Author: Chegu Vinod +Date: Mon Jun 24 03:49:41 2013 -0600 + + Introduce async_run_on_cpu() + + Introduce an asynchronous version of run_on_cpu() i.e. the caller + doesn't have to block till the call back routine finishes execution + on the target vcpu. + + Signed-off-by: Chegu Vinod + Reviewed-by: Paolo Bonzini + Signed-off-by: Juan Quintela + +diff --git a/cpus.c b/cpus.c +index c232265..8cd4eab 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -653,6 +653,7 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) + + wi.func = func; + wi.data = data; ++ wi.free = false; + if (cpu->queued_work_first == NULL) { + cpu->queued_work_first = &wi; + } else { +@@ -671,6 +672,31 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) + } + } + ++void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) ++{ ++ struct qemu_work_item *wi; ++ ++ if (qemu_cpu_is_self(cpu)) { ++ func(data); ++ return; ++ } ++ ++ wi = g_malloc0(sizeof(struct qemu_work_item)); ++ wi->func = func; ++ wi->data = data; ++ wi->free = true; ++ if (cpu->queued_work_first == NULL) { ++ cpu->queued_work_first = wi; ++ } else { ++ cpu->queued_work_last->next = wi; ++ } ++ cpu->queued_work_last = wi; ++ wi->next = NULL; ++ wi->done = false; ++ ++ qemu_cpu_kick(cpu); ++} ++ + static void flush_queued_work(CPUState *cpu) + { + struct qemu_work_item *wi; +@@ -683,6 +709,9 @@ static void flush_queued_work(CPUState *cpu) + cpu->queued_work_first = wi->next; + wi->func(wi->data); + wi->done = true; ++ if (wi->free) { ++ g_free(wi); ++ } + } + cpu->queued_work_last = NULL; + qemu_cond_broadcast(&qemu_work_cond); +diff --git a/include/qemu-common.h b/include/qemu-common.h +index 3b1ca8e..73c6419 100644 +--- a/include/qemu-common.h ++++ b/include/qemu-common.h +@@ -288,6 +288,7 @@ struct qemu_work_item { + void (*func)(void *data); + void *data; + int done; ++ bool free; + }; + + #ifdef CONFIG_USER_ONLY +diff --git a/include/qom/cpu.h b/include/qom/cpu.h +index 7cd9442..46465e9 100644 +--- a/include/qom/cpu.h ++++ b/include/qom/cpu.h +@@ -265,6 +265,16 @@ bool cpu_is_stopped(CPUState *cpu); + void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); + + /** ++ * async_run_on_cpu: ++ * @cpu: The vCPU to run on. ++ * @func: The function to be executed. ++ * @data: Data to pass to the function. ++ * ++ * Schedules the function @func for execution on the vCPU @cpu asynchronously. ++ */ ++void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data); ++ ++/** + * qemu_for_each_cpu: + * @func: The function to be executed. + * @data: Data to pass to the function. diff --git a/SOURCES/kvm-misc-add-qxl_screendump-monitor-command.patch b/SOURCES/kvm-misc-add-qxl_screendump-monitor-command.patch new file mode 100644 index 0000000..fe065f6 --- /dev/null +++ b/SOURCES/kvm-misc-add-qxl_screendump-monitor-command.patch @@ -0,0 +1,160 @@ +From b0abe7c2c3873172eee6020c49ca3a44567bb645 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:12:44 +0200 +Subject: add qxl_screendump monitor command + +RH-Author: Gerd Hoffmann +Message-id: <1375866764-17766-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 53033 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] add qxl_screendump monitor command +Bugzilla: 903910 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny + +This patch ports the rhel-6 specific qxl_screendump command to rhel-7. +qxl_screendump takes the device id as additional argument and thus can +be used to take screenshots from non-primary displays. + +The plan to get that functionality upstream in time failed, so we go for +plan b and carry forward the rhel-6 specific qxl_screendump command. +Thanks to the major console subsystem cleanups which made it upstream +the implementation is (a) alot less hackier than the rhel-6 one and (b) +not qxl-specific any more. Given that qxl is the only graphic device +which can work as secondary vga card the later is only a theoretical +benefit though ;) + +RHEL-6 commit: 1c6074d107dff93c7c7b0edfb5da871504802946 + +bugzilla: #903910 - RHEL7 does not have equivalent functionality for + __com.redhat_qxl_screendump + +Signed-off-by: Gerd Hoffmann + +diff --git a/hmp-commands.hx b/hmp-commands.hx +index 4f5a3fd..5cd6368 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -242,6 +242,13 @@ ETEXI + .help = "save screen into PPM image 'filename'", + .mhandler.cmd = hmp_screen_dump, + }, ++ { ++ .name = "__com.redhat_qxl_screendump", ++ .args_type = "id:s,filename:F", ++ .params = "id filename", ++ .help = "save screen from qxl device 'id' into PPM image 'filename'", ++ .mhandler.cmd = hmp___com_redhat_qxl_screen_dump, ++ }, + + STEXI + @item screendump @var{filename} +diff --git a/hmp.c b/hmp.c +index 4fb76ec..3b3e7c7 100644 +--- a/hmp.c ++++ b/hmp.c +@@ -1328,6 +1328,16 @@ void hmp_screen_dump(Monitor *mon, const QDict *qdict) + hmp_handle_error(mon, &err); + } + ++void hmp___com_redhat_qxl_screen_dump(Monitor *mon, const QDict *qdict) ++{ ++ const char *id = qdict_get_str(qdict, "id"); ++ const char *filename = qdict_get_str(qdict, "filename"); ++ Error *err = NULL; ++ ++ qmp___com_redhat_qxl_screendump(id, filename, &err); ++ hmp_handle_error(mon, &err); ++} ++ + void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) + { + const char *uri = qdict_get_str(qdict, "uri"); +diff --git a/hmp.h b/hmp.h +index 95fe76e..9b2c9ce 100644 +--- a/hmp.h ++++ b/hmp.h +@@ -80,6 +80,7 @@ void hmp_getfd(Monitor *mon, const QDict *qdict); + void hmp_closefd(Monitor *mon, const QDict *qdict); + void hmp_send_key(Monitor *mon, const QDict *qdict); + void hmp_screen_dump(Monitor *mon, const QDict *qdict); ++void hmp___com_redhat_qxl_screen_dump(Monitor *mon, const QDict *qdict); + void hmp_nbd_server_start(Monitor *mon, const QDict *qdict); + void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); + void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); +diff --git a/qapi-schema.json b/qapi-schema.json +index 537f1d1..54a802d 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -3123,6 +3123,21 @@ + { 'command': 'screendump', 'data': {'filename': 'str'} } + + ## ++# @__com.redhat_qxl_screendump: ++# ++# Write a PPM of secondary qxl devices to a file. ++# ++# @id: qxl device id ++# @filename: the path of a new PPM file to store the image ++# ++# Returns: Nothing on success ++# ++# Since: never (rhel-only, not upstream) ++## ++{ 'command': '__com.redhat_qxl_screendump', 'data': { 'id' : 'str', ++ 'filename': 'str' } } ++ ++## + # @nbd-server-start: + # + # Start an NBD server listening on the given host and port. Block +diff --git a/qmp-commands.hx b/qmp-commands.hx +index ffd130e..de5f394 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -148,6 +148,11 @@ EQMP + .args_type = "filename:F", + .mhandler.cmd_new = qmp_marshal_input_screendump, + }, ++ { ++ .name = "__com.redhat_qxl_screendump", ++ .args_type = "id:s,filename:F", ++ .mhandler.cmd_new = qmp_marshal_input___com_redhat_qxl_screendump, ++ }, + + SQMP + screendump +diff --git a/ui/console.c b/ui/console.c +index 28bba6d..d422083 100644 +--- a/ui/console.c ++++ b/ui/console.c +@@ -328,6 +328,29 @@ void qmp_screendump(const char *filename, Error **errp) + ppm_save(filename, surface, errp); + } + ++void qmp___com_redhat_qxl_screendump(const char *id, const char *filename, Error **errp) ++{ ++ DeviceState *dev; ++ QemuConsole *con; ++ DisplaySurface *surface; ++ ++ dev = qdev_find_recursive(sysbus_get_default(), id); ++ if (NULL == dev) { ++ error_set(errp, QERR_DEVICE_NOT_FOUND, id); ++ return; ++ } ++ ++ con = qemu_console_lookup_by_device(dev); ++ if (con == NULL) { ++ error_setg(errp, "Device %s has no QemuConsole attached to it.", id); ++ return; ++ } ++ ++ graphic_hw_update(con); ++ surface = qemu_console_surface(con); ++ ppm_save(filename, surface, errp); ++} ++ + void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) + { + if (!con) { diff --git a/SOURCES/kvm-misc-qga-fsfreeze-main-hook-adapt-to-RHEL-7-RH-only.patch b/SOURCES/kvm-misc-qga-fsfreeze-main-hook-adapt-to-RHEL-7-RH-only.patch new file mode 100644 index 0000000..3657454 --- /dev/null +++ b/SOURCES/kvm-misc-qga-fsfreeze-main-hook-adapt-to-RHEL-7-RH-only.patch @@ -0,0 +1,78 @@ +From e936dcde086c84c08102f821c99381005acd272a Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 22:15:05 +0200 +Subject: qga fsfreeze main hook: adapt to RHEL-7 (RH only) + +RH-Author: Laszlo Ersek +Message-id: <1375308906-23405-3-git-send-email-lersek@redhat.com> +Patchwork-id: 52885 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 2/3] qga fsfreeze main hook: adapt to RHEL-7 (RH only) +Bugzilla: 969942 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michal Novotny +RH-Acked-by: Miroslav Rezanina + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=969942 + +LOGFILE should look like it does on RHEL-6. + +The main fsfreeze script should process hook files like systemd does +[Paolo]. + +Signed-off-by: Laszlo Ersek + +diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook +index c27b29f..45514fa 100755 +--- a/scripts/qemu-guest-agent/fsfreeze-hook ++++ b/scripts/qemu-guest-agent/fsfreeze-hook +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/bin/bash + + # This script is executed when a guest agent receives fsfreeze-freeze and + # fsfreeze-thaw command, if it is specified in --fsfreeze-hook (-F) +@@ -7,8 +7,7 @@ + # "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw + # request, it is issued with "thaw" argument after filesystem is thawed. + +-LOGFILE=/var/log/qga-fsfreeze-hook.log +-FSFREEZE_D=$(dirname -- "$0")/fsfreeze-hook.d ++LOGFILE=/var/log/qemu-ga.fsfreeze-hook.log + + # Check whether file $1 is a backup or rpm-generated file and should be ignored + is_ignored_file() { +@@ -19,15 +18,26 @@ is_ignored_file() { + return 1 + } + +-# Iterate executables in directory "fsfreeze-hook.d" with the specified args +-[ ! -d "$FSFREEZE_D" ] && exit 0 +-for file in "$FSFREEZE_D"/* ; do +- is_ignored_file "$file" && continue +- [ -x "$file" ] || continue +- printf "$(date): execute $file $@\n" >>$LOGFILE +- "$file" "$@" >>$LOGFILE 2>&1 ++shopt -s nullglob ++RELPATH=qemu-ga/fsfreeze-hook.d ++ ++for DIR in lib etc run; do ++ for FILE in /"$DIR/$RELPATH"/*; do ++ if is_ignored_file "$FILE" || ! [ -x "$FILE" ]; then ++ continue ++ fi ++ BNAME=$(basename -- "$FILE") ++ if ( [ lib = "$DIR" ] && ( [ -e /etc/"$RELPATH/$BNAME" ] || ++ [ -e /run/"$RELPATH/$BNAME" ] ) ) || ++ ( [ etc = "$DIR" ] && ( [ -e /run/"$RELPATH/$BNAME" ] ) ); then ++ continue ++ fi ++ ++ printf "$(date): execute $FILE $@\n" >>$LOGFILE ++ "$FILE" "$@" >>$LOGFILE 2>&1 + STATUS=$? +- printf "$(date): $file finished with status=$STATUS\n" >>$LOGFILE ++ printf "$(date): $FILE finished with status=$STATUS\n" >>$LOGFILE ++ done + done + + exit 0 diff --git a/SOURCES/kvm-monitor-Remove-host_net_add-remove-for-Red-Hat-Enter.patch b/SOURCES/kvm-monitor-Remove-host_net_add-remove-for-Red-Hat-Enter.patch new file mode 100644 index 0000000..b244126 --- /dev/null +++ b/SOURCES/kvm-monitor-Remove-host_net_add-remove-for-Red-Hat-Enter.patch @@ -0,0 +1,59 @@ +From 35ba7fa1285b9350fe4f9507b314ef11b74064eb Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 6 Nov 2013 12:36:04 +0100 +Subject: [PATCH 69/81] monitor: Remove host_net_add/remove for Red Hat Enterprise Linux + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 55519 +O-Subject: [RHEL7 qemu-kvm PATCH v2 4/4] monitor: Remove host_net_add/remove for Red Hat Enterprise Linux +Bugzilla: 1010858 +RH-Acked-by: Michal Novotny +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eric Blake + +From: Miroslav Rezanina + +This is forwardport of RHEL-6 commit dd94505bd1b826db0c7e155ccee5c24f77987f16: + + monitor: Remove host_net_add/remove for Red Hat Enterprise Linux + + The host_net_add/remove commands are replaced by netdev_add/del. Remove + them. + + Signed-off-by: Amit Shah + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hmp-commands.hx b/hmp-commands.hx +index 74774bd..c881e01 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -1148,6 +1148,7 @@ STEXI + Inject PCIe AER error + ETEXI + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + { + .name = "host_net_add", + .args_type = "device:s,opts:s?", +@@ -1175,6 +1176,7 @@ STEXI + @findex host_net_remove + Remove host VLAN client. + ETEXI ++#endif + + { + .name = "netdev_add", +-- +1.7.1 + diff --git a/SOURCES/kvm-monitor-Remove-pci_add-command-for-Red-Hat-Enterpris.patch b/SOURCES/kvm-monitor-Remove-pci_add-command-for-Red-Hat-Enterpris.patch new file mode 100644 index 0000000..d53b3b2 --- /dev/null +++ b/SOURCES/kvm-monitor-Remove-pci_add-command-for-Red-Hat-Enterpris.patch @@ -0,0 +1,52 @@ +From 21aa0c54586f48e3fe51c71138b853977a4d8a66 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 6 Nov 2013 12:36:01 +0100 +Subject: [PATCH 66/81] monitor: Remove pci_add command for Red Hat Enterprise Linux + +RH-Author: Miroslav Rezanina +Message-id: <2e280a8060b33499eae1704843285ceb7f602470.1383741033.git.mrezanin@redhat.com> +Patchwork-id: 55518 +O-Subject: [RHEL7 qemu-kvm PATCH v2 1/4] monitor: Remove pci_add command for Red Hat Enterprise Linux +Bugzilla: 1010858 +RH-Acked-by: Michal Novotny +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eric Blake + +From: Miroslav Rezanina + +This is forwardport of RHEL-6 commit 22aef6c9882ac60bcf3df98e67c4b9b729a90707: + + monitor: Remove pci_add command for Red Hat Enterprise Linux + + pci_add is the old way of hot-plugging pci (nic or storage) devices. + The newer device_add is the recommended and suggested command. + + Signed-off-by: Amit Shah + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hmp-commands.hx b/hmp-commands.hx +index 2fc2c0b..d5ec349 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -1089,7 +1089,7 @@ STEXI + Add drive to PCI storage controller. + ETEXI + +-#if defined(TARGET_I386) ++#if defined(TARGET_I386) && 0 /* Disabled for Red Hat Enterprise Linux */ + { + .name = "pci_add", + .args_type = "pci_addr:s,type:s,opts:s?", +-- +1.7.1 + diff --git a/SOURCES/kvm-monitor-Remove-pci_del-command-for-Red-Hat-Enterpris.patch b/SOURCES/kvm-monitor-Remove-pci_del-command-for-Red-Hat-Enterpris.patch new file mode 100644 index 0000000..30f809b --- /dev/null +++ b/SOURCES/kvm-monitor-Remove-pci_del-command-for-Red-Hat-Enterpris.patch @@ -0,0 +1,52 @@ +From 8ab120f6ad6629e826ded6d8f910c91f441bafd4 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 6 Nov 2013 12:36:02 +0100 +Subject: [PATCH 67/81] monitor: Remove pci_del command for Red Hat Enterprise Linux + +RH-Author: Miroslav Rezanina +Message-id: <6e7cc8214fdc2fd6a95a7446c667bf36fc13f3ce.1383741033.git.mrezanin@redhat.com> +Patchwork-id: 55517 +O-Subject: [RHEL7 qemu-kvm PATCH v2 2/4] monitor: Remove pci_del command for Red Hat Enterprise Linux +Bugzilla: 1010858 +RH-Acked-by: Michal Novotny +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eric Blake + +From: Miroslav Rezanina + +This is forwardport of RHEL-6 commit 609b9f16a7443e86e55a3cdc76a484253e50267b: + + monitor: Remove pci_del command for Red Hat Enterprise Linux + + pci_del is the old way of hot-unplugging pci (nic or storage) devices. + The newer device_del is the recommended and suggested command. + + Signed-off-by: Amit Shah + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hmp-commands.hx b/hmp-commands.hx +index d5ec349..14ba536 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -1105,7 +1105,7 @@ STEXI + Hot-add PCI device. + ETEXI + +-#if defined(TARGET_I386) ++#if defined(TARGET_I386) && 0 /* Disabled for Red Hat Enterprise Linux */ + { + .name = "pci_del", + .args_type = "pci_addr:s", +-- +1.7.1 + diff --git a/SOURCES/kvm-monitor-Remove-usb_add-del-commands-for-Red-Hat-Ente.patch b/SOURCES/kvm-monitor-Remove-usb_add-del-commands-for-Red-Hat-Ente.patch new file mode 100644 index 0000000..13c2e78 --- /dev/null +++ b/SOURCES/kvm-monitor-Remove-usb_add-del-commands-for-Red-Hat-Ente.patch @@ -0,0 +1,59 @@ +From a1ee2aaadfe464751e42b795d9800c6e04332029 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 6 Nov 2013 12:36:03 +0100 +Subject: [PATCH 68/81] monitor: Remove usb_add/del commands for Red Hat Enterprise Linux + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 55520 +O-Subject: [RHEL7 qemu-kvm PATCH v2 3/4] monitor: Remove usb_add/del commands for Red Hat Enterprise Linux +Bugzilla: 1010858 +RH-Acked-by: Michal Novotny +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eric Blake + +From: Miroslav Rezanina + +This is forwardport of RHEL-6 commit 754e6292b4ab41c8848171555af830ab7284f4d3: + + monitor: Remove usb_add/del commands for Red Hat Enterprise Linux + + The usb_add/del commands have been obsoleted by the device_add/del + commands. + + Signed-off-by: Amit Shah + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hmp-commands.hx | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hmp-commands.hx b/hmp-commands.hx +index 14ba536..74774bd 100644 +--- a/hmp-commands.hx ++++ b/hmp-commands.hx +@@ -621,6 +621,7 @@ STEXI + Compute the checksum of a memory region. + ETEXI + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + { + .name = "usb_add", + .args_type = "devname:s", +@@ -653,6 +654,7 @@ Remove the USB device @var{devname} from the QEMU virtual USB + hub. @var{devname} has the syntax @code{bus.addr}. Use the monitor + command @code{info usb} to see the devices you can remove. + ETEXI ++#endif + + { + .name = "device_add", +-- +1.7.1 + diff --git a/SOURCES/kvm-monitor-maintain-at-most-one-G_IO_OUT-watch.patch b/SOURCES/kvm-monitor-maintain-at-most-one-G_IO_OUT-watch.patch new file mode 100644 index 0000000..fb2c407 --- /dev/null +++ b/SOURCES/kvm-monitor-maintain-at-most-one-G_IO_OUT-watch.patch @@ -0,0 +1,75 @@ +From 6d8b03e0e91a58a0b276e76363e0c836827c9a49 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 19 Jul 2013 13:05:23 +0200 +Subject: monitor: maintain at most one G_IO_OUT watch + +RH-Author: Laszlo Ersek +Message-id: <1374239123-4841-3-git-send-email-lersek@redhat.com> +Patchwork-id: 52616 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/2] monitor: maintain at most one G_IO_OUT watch +Bugzilla: 970047 +RH-Acked-by: Amit Shah +RH-Acked-by: Markus Armbruster +RH-Acked-by: Luiz Capitulino + +When monitor_flush() is invoked repeatedly outside the monitor_unblocked() +callback, for example from tlb_info() -> ... -> print_pte(), several +watches may be added for the same event. + +This is no problem per se because the extra monitor_unblocked() callbacks +are harmless if mon->outbuf is empty, the watches will be removed +gradually. However a big number of watches can grow "gpollfds" without +limit in glib_pollfds_fill(), triggering a -1/EINVAL condition in +g_poll(). + +Keep at most one such watch, by following the pattern observable in eg. +commits c874ea97 and c3d6b96e. The change has no effect when +monitor_unblocked() calls monitor_flush() (when the watch can either be +removed or renewed 1-for-1), but non-callback contexts won't create an +additional watch when the monitor already has one. + +Related RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=970047 + +Signed-off-by: Laszlo Ersek +Reviewed-by: Amit Shah +Reviewed-by: Anthony Liguori +Message-id: 1373998781-29561-3-git-send-email-lersek@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 293d2a0014a0e849477413f55aaa05f2743b2e04) + +diff --git a/monitor.c b/monitor.c +index dee980c..deb0dc8 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -190,6 +190,7 @@ struct Monitor { + int suspend_cnt; + bool skip_flush; + QString *outbuf; ++ guint watch; + ReadLineState *rs; + MonitorControl *mc; + CPUArchState *mon_cpu; +@@ -264,7 +265,10 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, + static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, + void *opaque) + { +- monitor_flush(opaque); ++ Monitor *mon = opaque; ++ ++ mon->watch = 0; ++ monitor_flush(mon); + return FALSE; + } + +@@ -295,7 +299,10 @@ void monitor_flush(Monitor *mon) + QDECREF(mon->outbuf); + mon->outbuf = tmp; + } +- qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, monitor_unblocked, mon); ++ if (mon->watch == 0) { ++ mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT, ++ monitor_unblocked, mon); ++ } + } + } + diff --git a/SOURCES/kvm-net-add-support-of-mac-programming-over-macvtap-in-Q.patch b/SOURCES/kvm-net-add-support-of-mac-programming-over-macvtap-in-Q.patch new file mode 100644 index 0000000..a855692 --- /dev/null +++ b/SOURCES/kvm-net-add-support-of-mac-programming-over-macvtap-in-Q.patch @@ -0,0 +1,646 @@ +From 8eab8301249fa8f5b3f68a91a87edac676ff7f0f Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Fri, 8 Nov 2013 06:13:59 +0100 +Subject: [PATCH 4/4] net: add support of mac-programming over macvtap in QEMU side + +RH-Author: Amos Kong +Message-id: <1383891239-29531-5-git-send-email-akong@redhat.com> +Patchwork-id: 55611 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 4/4] net: add support of mac-programming over macvtap in QEMU side +Bugzilla: 848203 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Currently macvtap based macvlan device is working in promiscuous +mode, we want to implement mac-programming over macvtap through +Libvirt for better performance. + +Design: + QEMU notifies Libvirt when rx-filter config is changed in guest, + then Libvirt query the rx-filter information by a monitor command, + and sync the change to macvtap device. Related rx-filter config + of the nic contains main mac, rx-mode items and vlan table. + +This patch adds a QMP event to notify management of rx-filter change, +and adds a monitor command for management to query rx-filter +information. + +Test: + If we repeatedly add/remove vlan, and change macaddr of vlan + interfaces in guest by a loop script. + +Result: + The events will flood the QMP client(management), management takes + too much resource to process the events. + + Event_throttle API (set rate to 1 ms) can avoid the events to flood + QMP client, but it could cause an unexpected delay (~1ms), guests + guests normally expect rx-filter updates immediately. + + So we use a flag for each nic to avoid events flooding, the event + is emitted once until the query command is executed. The flag + implementation could not introduce unexpected delay. + +There maybe exist an uncontrollable delay if we let Libvirt do the +real change, guests normally expect rx-filter updates immediately. +But it's another separate issue, we can investigate it when the +work in Libvirt side is done. + +Michael S. Tsirkin: tweaked to enable events on start +Michael S. Tsirkin: fixed not to crash when no id +Michael S. Tsirkin: fold in patch: + "additional fixes for mac-programming feature" +Amos Kong: always notify QMP client if mactable is changed +Amos Kong: return NULL list if no net client supports rx-filter query + +Reviewed-by: Eric Blake +Reviewed-by: Markus Armbruster +Signed-off-by: Amos Kong +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit b1be42803b31a913bab65bab563a8760ad2e7f7f) +--- + QMP/qmp-events.txt | 17 ++++++ + hw/net/virtio-net.c | 133 +++++++++++++++++++++++++++++++++++++++++++-- + include/monitor/monitor.h | 1 + + include/net/net.h | 3 + + monitor.c | 1 + + net/net.c | 48 ++++++++++++++++ + qapi-schema.json | 77 ++++++++++++++++++++++++++- + qmp-commands.hx | 64 ++++++++++++++++++++++ + 8 files changed, 337 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + QMP/qmp-events.txt | 17 ++++++ + hw/net/virtio-net.c | 133 +++++++++++++++++++++++++++++++++++++++++++-- + include/monitor/monitor.h | 1 + + include/net/net.h | 3 + + monitor.c | 1 + + net/net.c | 48 ++++++++++++++++ + qapi-schema.json | 77 ++++++++++++++++++++++++++- + qmp-commands.hx | 64 ++++++++++++++++++++++ + 8 files changed, 337 insertions(+), 7 deletions(-) + +diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt +index e185030..79fb1c9 100644 +--- a/QMP/qmp-events.txt ++++ b/QMP/qmp-events.txt +@@ -194,6 +194,23 @@ Data: + }, + "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } + ++NIC_RX_FILTER_CHANGED ++----------------- ++ ++The event is emitted once until the query command is executed, ++the first event will always be emitted. ++ ++Data: ++ ++- "name": net client name (json-string) ++- "path": device path (json-string) ++ ++{ "event": "NIC_RX_FILTER_CHANGED", ++ "data": { "name": "vnet0", ++ "path": "/machine/peripheral/vnet0/virtio-backend" }, ++ "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } ++} ++ + RESET + ----- + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 3290013..19c5030 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -21,6 +21,8 @@ + #include "hw/virtio/virtio-net.h" + #include "net/vhost_net.h" + #include "hw/virtio/virtio-bus.h" ++#include "qapi/qmp/qjson.h" ++#include "monitor/monitor.h" + + #define VIRTIO_NET_VM_VERSION 11 + +@@ -192,6 +194,105 @@ static void virtio_net_set_link_status(NetClientState *nc) + virtio_net_set_status(vdev, vdev->status); + } + ++static void rxfilter_notify(NetClientState *nc) ++{ ++ QObject *event_data; ++ VirtIONet *n = qemu_get_nic_opaque(nc); ++ ++ if (nc->rxfilter_notify_enabled) { ++ if (n->netclient_name) { ++ event_data = qobject_from_jsonf("{ 'name': %s, 'path': %s }", ++ n->netclient_name, ++ object_get_canonical_path(OBJECT(n->qdev))); ++ } else { ++ event_data = qobject_from_jsonf("{ 'path': %s }", ++ object_get_canonical_path(OBJECT(n->qdev))); ++ } ++ monitor_protocol_event(QEVENT_NIC_RX_FILTER_CHANGED, event_data); ++ qobject_decref(event_data); ++ ++ /* disable event notification to avoid events flooding */ ++ nc->rxfilter_notify_enabled = 0; ++ } ++} ++ ++static char *mac_strdup_printf(const uint8_t *mac) ++{ ++ return g_strdup_printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac[0], ++ mac[1], mac[2], mac[3], mac[4], mac[5]); ++} ++ ++static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) ++{ ++ VirtIONet *n = qemu_get_nic_opaque(nc); ++ RxFilterInfo *info; ++ strList *str_list, *entry; ++ intList *int_list, *int_entry; ++ int i, j; ++ ++ info = g_malloc0(sizeof(*info)); ++ info->name = g_strdup(nc->name); ++ info->promiscuous = n->promisc; ++ ++ if (n->nouni) { ++ info->unicast = RX_STATE_NONE; ++ } else if (n->alluni) { ++ info->unicast = RX_STATE_ALL; ++ } else { ++ info->unicast = RX_STATE_NORMAL; ++ } ++ ++ if (n->nomulti) { ++ info->multicast = RX_STATE_NONE; ++ } else if (n->allmulti) { ++ info->multicast = RX_STATE_ALL; ++ } else { ++ info->multicast = RX_STATE_NORMAL; ++ } ++ ++ info->broadcast_allowed = n->nobcast; ++ info->multicast_overflow = n->mac_table.multi_overflow; ++ info->unicast_overflow = n->mac_table.uni_overflow; ++ ++ info->main_mac = mac_strdup_printf(n->mac); ++ ++ str_list = NULL; ++ for (i = 0; i < n->mac_table.first_multi; i++) { ++ entry = g_malloc0(sizeof(*entry)); ++ entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); ++ entry->next = str_list; ++ str_list = entry; ++ } ++ info->unicast_table = str_list; ++ ++ str_list = NULL; ++ for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { ++ entry = g_malloc0(sizeof(*entry)); ++ entry->value = mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); ++ entry->next = str_list; ++ str_list = entry; ++ } ++ info->multicast_table = str_list; ++ ++ int_list = NULL; ++ for (i = 0; i < MAX_VLAN >> 5; i++) { ++ for (j = 0; n->vlans[i] && j < 0x1f; j++) { ++ if (n->vlans[i] & (1U << j)) { ++ int_entry = g_malloc0(sizeof(*int_entry)); ++ int_entry->value = (i << 5) + j; ++ int_entry->next = int_list; ++ int_list = int_entry; ++ } ++ } ++ } ++ info->vlan_table = int_list; ++ ++ /* enable event notification after query */ ++ nc->rxfilter_notify_enabled = 1; ++ ++ return info; ++} ++ + static void virtio_net_reset(VirtIODevice *vdev) + { + VirtIONet *n = VIRTIO_NET(vdev); +@@ -396,6 +497,7 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, + { + uint8_t on; + size_t s; ++ NetClientState *nc = qemu_get_queue(n->nic); + + s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on)); + if (s != sizeof(on)) { +@@ -418,6 +520,8 @@ static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, + return VIRTIO_NET_ERR; + } + ++ rxfilter_notify(nc); ++ + return VIRTIO_NET_OK; + } + +@@ -426,6 +530,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, + { + struct virtio_net_ctrl_mac mac_data; + size_t s; ++ NetClientState *nc = qemu_get_queue(n->nic); + + if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) { + if (iov_size(iov, iov_cnt) != sizeof(n->mac)) { +@@ -434,6 +539,8 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, + s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac)); + assert(s == sizeof(n->mac)); + qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); ++ rxfilter_notify(nc); ++ + return VIRTIO_NET_OK; + } + +@@ -451,19 +558,19 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, + sizeof(mac_data.entries)); + mac_data.entries = ldl_p(&mac_data.entries); + if (s != sizeof(mac_data.entries)) { +- return VIRTIO_NET_ERR; ++ goto error; + } + iov_discard_front(&iov, &iov_cnt, s); + + if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) { +- return VIRTIO_NET_ERR; ++ goto error; + } + + if (mac_data.entries <= MAC_TABLE_ENTRIES) { + s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs, + mac_data.entries * ETH_ALEN); + if (s != mac_data.entries * ETH_ALEN) { +- return VIRTIO_NET_ERR; ++ goto error; + } + n->mac_table.in_use += mac_data.entries; + } else { +@@ -478,27 +585,33 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, + sizeof(mac_data.entries)); + mac_data.entries = ldl_p(&mac_data.entries); + if (s != sizeof(mac_data.entries)) { +- return VIRTIO_NET_ERR; ++ goto error; + } + + iov_discard_front(&iov, &iov_cnt, s); + + if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) { +- return VIRTIO_NET_ERR; ++ goto error; + } + + if (n->mac_table.in_use + mac_data.entries <= MAC_TABLE_ENTRIES) { + s = iov_to_buf(iov, iov_cnt, 0, n->mac_table.macs, + mac_data.entries * ETH_ALEN); + if (s != mac_data.entries * ETH_ALEN) { +- return VIRTIO_NET_ERR; ++ goto error; + } + n->mac_table.in_use += mac_data.entries; + } else { + n->mac_table.multi_overflow = 1; + } + ++ rxfilter_notify(nc); ++ + return VIRTIO_NET_OK; ++ ++error: ++ rxfilter_notify(nc); ++ return VIRTIO_NET_ERR; + } + + static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, +@@ -506,6 +619,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, + { + uint16_t vid; + size_t s; ++ NetClientState *nc = qemu_get_queue(n->nic); + + s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid)); + vid = lduw_p(&vid); +@@ -523,6 +637,8 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, + else + return VIRTIO_NET_ERR; + ++ rxfilter_notify(nc); ++ + return VIRTIO_NET_OK; + } + +@@ -1244,6 +1360,7 @@ static NetClientInfo net_virtio_info = { + .receive = virtio_net_receive, + .cleanup = virtio_net_cleanup, + .link_status_changed = virtio_net_set_link_status, ++ .query_rx_filter = virtio_net_query_rxfilter, + }; + + static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) +@@ -1305,6 +1422,7 @@ static int virtio_net_device_init(VirtIODevice *vdev) + + DeviceState *qdev = DEVICE(vdev); + VirtIONet *n = VIRTIO_NET(vdev); ++ NetClientState *nc; + + virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET, + n->config_size); +@@ -1371,6 +1489,9 @@ static int virtio_net_device_init(VirtIODevice *vdev) + + n->vlans = g_malloc0(MAX_VLAN >> 3); + ++ nc = qemu_get_queue(n->nic); ++ nc->rxfilter_notify_enabled = 1; ++ + n->qdev = qdev; + register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION, + virtio_net_save, virtio_net_load, n); +diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h +index 07b41a6..10fa0e3 100644 +--- a/include/monitor/monitor.h ++++ b/include/monitor/monitor.h +@@ -41,6 +41,7 @@ typedef enum MonitorEvent { + QEVENT_BLOCK_JOB_READY, + QEVENT_DEVICE_DELETED, + QEVENT_DEVICE_TRAY_MOVED, ++ QEVENT_NIC_RX_FILTER_CHANGED, + QEVENT_SUSPEND, + QEVENT_SUSPEND_DISK, + QEVENT_WAKEUP, +diff --git a/include/net/net.h b/include/net/net.h +index 43d85a1..30e4b04 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -49,6 +49,7 @@ typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); + typedef void (NetCleanup) (NetClientState *); + typedef void (LinkStatusChanged)(NetClientState *); + typedef void (NetClientDestructor)(NetClientState *); ++typedef RxFilterInfo *(QueryRxFilter)(NetClientState *); + + typedef struct NetClientInfo { + NetClientOptionsKind type; +@@ -59,6 +60,7 @@ typedef struct NetClientInfo { + NetCanReceive *can_receive; + NetCleanup *cleanup; + LinkStatusChanged *link_status_changed; ++ QueryRxFilter *query_rx_filter; + NetPoll *poll; + } NetClientInfo; + +@@ -74,6 +76,7 @@ struct NetClientState { + unsigned receive_disabled : 1; + NetClientDestructor *destructor; + unsigned int queue_index; ++ unsigned rxfilter_notify_enabled:1; + }; + + typedef struct NICState { +diff --git a/monitor.c b/monitor.c +index c226acf..8f36f91 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -498,6 +498,7 @@ static const char *monitor_event_names[] = { + [QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY", + [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED", + [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED", ++ [QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED", + [QEVENT_SUSPEND] = "SUSPEND", + [QEVENT_SUSPEND_DISK] = "SUSPEND_DISK", + [QEVENT_WAKEUP] = "WAKEUP", +diff --git a/net/net.c b/net/net.c +index 43a74e4..c0d61bf 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -961,6 +961,54 @@ void print_net_client(Monitor *mon, NetClientState *nc) + nc->info_str); + } + ++RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name, ++ Error **errp) ++{ ++ NetClientState *nc; ++ RxFilterInfoList *filter_list = NULL, *last_entry = NULL; ++ ++ QTAILQ_FOREACH(nc, &net_clients, next) { ++ RxFilterInfoList *entry; ++ RxFilterInfo *info; ++ ++ if (has_name && strcmp(nc->name, name) != 0) { ++ continue; ++ } ++ ++ /* only query rx-filter information of NIC */ ++ if (nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC) { ++ if (has_name) { ++ error_setg(errp, "net client(%s) isn't a NIC", name); ++ break; ++ } ++ continue; ++ } ++ ++ if (nc->info->query_rx_filter) { ++ info = nc->info->query_rx_filter(nc); ++ entry = g_malloc0(sizeof(*entry)); ++ entry->value = info; ++ ++ if (!filter_list) { ++ filter_list = entry; ++ } else { ++ last_entry->next = entry; ++ } ++ last_entry = entry; ++ } else if (has_name) { ++ error_setg(errp, "net client(%s) doesn't support" ++ " rx-filter querying", name); ++ break; ++ } ++ } ++ ++ if (filter_list == NULL && !error_is_set(errp) && has_name) { ++ error_setg(errp, "invalid net client name: %s", name); ++ } ++ ++ return filter_list; ++} ++ + void do_info_network(Monitor *mon, const QDict *qdict) + { + NetClientState *nc, *peer; +diff --git a/qapi-schema.json b/qapi-schema.json +index 64696a9..92fcd54 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -3737,7 +3737,6 @@ + 'cpuid-register': 'X86CPURegister32', + 'features': 'int' } } + +- + ## + # @BlockdevDiscardOptions + # +@@ -3972,3 +3971,79 @@ + # Since: 1.7 + ## + { 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } } ++ ++## ++# @RxState: ++# ++# Packets receiving state ++# ++# @normal: filter assigned packets according to the mac-table ++# ++# @none: don't receive any assigned packet ++# ++# @all: receive all assigned packets ++# ++# Since: 1.6 ++## ++{ 'enum': 'RxState', 'data': [ 'normal', 'none', 'all' ] } ++ ++## ++# @RxFilterInfo: ++# ++# Rx-filter information for a NIC. ++# ++# @name: net client name ++# ++# @promiscuous: whether promiscuous mode is enabled ++# ++# @multicast: multicast receive state ++# ++# @unicast: unicast receive state ++# ++# @broadcast-allowed: whether to receive broadcast ++# ++# @multicast-overflow: multicast table is overflowed or not ++# ++# @unicast-overflow: unicast table is overflowed or not ++# ++# @main-mac: the main macaddr string ++# ++# @vlan-table: a list of active vlan id ++# ++# @unicast-table: a list of unicast macaddr string ++# ++# @multicast-table: a list of multicast macaddr string ++# ++# Since 1.6 ++## ++ ++{ 'type': 'RxFilterInfo', ++ 'data': { ++ 'name': 'str', ++ 'promiscuous': 'bool', ++ 'multicast': 'RxState', ++ 'unicast': 'RxState', ++ 'broadcast-allowed': 'bool', ++ 'multicast-overflow': 'bool', ++ 'unicast-overflow': 'bool', ++ 'main-mac': 'str', ++ 'vlan-table': ['int'], ++ 'unicast-table': ['str'], ++ 'multicast-table': ['str'] }} ++ ++## ++# @query-rx-filter: ++# ++# Return rx-filter information for all NICs (or for the given NIC). ++# ++# @name: #optional net client name ++# ++# Returns: list of @RxFilterInfo for all NICs (or for the given NIC). ++# Returns an error if the given @name doesn't exist, or given ++# NIC doesn't support rx-filter querying, or given net client ++# isn't a NIC. ++# ++# Since: 1.6 ++## ++{ 'command': 'query-rx-filter', 'data': { '*name': 'str' }, ++ 'returns': ['RxFilterInfo'] } +diff --git a/qmp-commands.hx b/qmp-commands.hx +index f71c34e..4942590 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -3061,3 +3061,67 @@ Example (2): + <- { "return": {} } + + EQMP ++ ++ { ++ .name = "query-rx-filter", ++ .args_type = "name:s?", ++ .mhandler.cmd_new = qmp_marshal_input_query_rx_filter, ++ }, ++ ++SQMP ++query-rx-filter ++--------------- ++ ++Show rx-filter information. ++ ++Returns a json-array of rx-filter information for all NICs (or for the ++given NIC), returning an error if the given NIC doesn't exist, or ++given NIC doesn't support rx-filter querying, or given net client ++isn't a NIC. ++ ++The query will clear the event notification flag of each NIC, then qemu ++will start to emit event to QMP monitor. ++ ++Each array entry contains the following: ++ ++- "name": net client name (json-string) ++- "promiscuous": promiscuous mode is enabled (json-bool) ++- "multicast": multicast receive state (one of 'normal', 'none', 'all') ++- "unicast": unicast receive state (one of 'normal', 'none', 'all') ++- "broadcast-allowed": allow to receive broadcast (json-bool) ++- "multicast-overflow": multicast table is overflowed (json-bool) ++- "unicast-overflow": unicast table is overflowed (json-bool) ++- "main-mac": main macaddr string (json-string) ++- "vlan-table": a json-array of active vlan id ++- "unicast-table": a json-array of unicast macaddr string ++- "multicast-table": a json-array of multicast macaddr string ++ ++Example: ++ ++-> { "execute": "query-rx-filter", "arguments": { "name": "vnet0" } } ++<- { "return": [ ++ { ++ "promiscuous": true, ++ "name": "vnet0", ++ "main-mac": "52:54:00:12:34:56", ++ "unicast": "normal", ++ "vlan-table": [ ++ 4, ++ 0 ++ ], ++ "unicast-table": [ ++ ], ++ "multicast": "normal", ++ "multicast-overflow": false, ++ "unicast-overflow": false, ++ "multicast-table": [ ++ "01:00:5e:00:00:01", ++ "33:33:00:00:00:01", ++ "33:33:ff:12:34:56" ++ ], ++ "broadcast-allowed": false ++ } ++ ] ++ } ++ ++EQMP +-- +1.7.1 + diff --git a/SOURCES/kvm-net-e1000-update-network-information-when-macaddr-is.patch b/SOURCES/kvm-net-e1000-update-network-information-when-macaddr-is.patch new file mode 100644 index 0000000..7210415 --- /dev/null +++ b/SOURCES/kvm-net-e1000-update-network-information-when-macaddr-is.patch @@ -0,0 +1,59 @@ +From 7825ef61b703c017c2b4ae56007046f0acd3fee6 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Tue, 5 Nov 2013 09:17:40 +0100 +Subject: [PATCH 08/25] net/e1000: update network information when macaddr is changed in guest + +RH-Author: Amos Kong +Message-id: <1383643062-1844-3-git-send-email-akong@redhat.com> +Patchwork-id: 55369 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 2/4] net/e1000: update network information when macaddr is changed in guest +Bugzilla: 922589 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Alex Williamson +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 922589 + +If we change macaddr in guest by 'ifconfig eth0 hw ether 12:12:12:34:35:36', +the mac register of e1000 is already updated, but we don't update +network information in qemu. Therefor, the information in monitor +is wrong. + +This patch updates nic info when the second part of macaddr is written. + +Signed-off-by: Amos Kong +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 7c36507c2b8776266f50c5e2739bd18279953b93) +--- + hw/net/e1000.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/net/e1000.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index d273ef2..87a84a7 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -971,7 +971,15 @@ mac_read_clr8(E1000State *s, int index) + static void + mac_writereg(E1000State *s, int index, uint32_t val) + { ++ uint32_t macaddr[2]; ++ + s->mac_reg[index] = val; ++ ++ if (index == RA + 1) { ++ macaddr[0] = cpu_to_le32(s->mac_reg[RA]); ++ macaddr[1] = cpu_to_le32(s->mac_reg[RA + 1]); ++ qemu_format_nic_info_str(qemu_get_queue(s->nic), (uint8_t *)macaddr); ++ } + } + + static void +-- +1.7.1 + diff --git a/SOURCES/kvm-net-rtl8139-update-network-information-when-macaddr-.patch b/SOURCES/kvm-net-rtl8139-update-network-information-when-macaddr-.patch new file mode 100644 index 0000000..6ca3f82 --- /dev/null +++ b/SOURCES/kvm-net-rtl8139-update-network-information-when-macaddr-.patch @@ -0,0 +1,55 @@ +From 1e7727e27ed91dd30b477ef7b78b0f05aba5a364 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Tue, 5 Nov 2013 09:17:41 +0100 +Subject: [PATCH 09/25] net/rtl8139: update network information when macaddr is changed in guest + +RH-Author: Amos Kong +Message-id: <1383643062-1844-4-git-send-email-akong@redhat.com> +Patchwork-id: 55370 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 3/4] net/rtl8139: update network information when macaddr is changed in guest +Bugzilla: 922589 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Alex Williamson +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 922589 + +rtl8139 has same problem as e1000, nic info isn't updated when macaddr +is changed in guest. + +This patch updates the nic info when the last bit of macaddr is written. + +Signed-off-by: Amos Kong +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 23c37c37f0280761072c23bf67d3a4f3c0ff25aa) +--- + hw/net/rtl8139.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/net/rtl8139.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 3ff5518..d08106b 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -2722,8 +2722,12 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val) + + switch (addr) + { +- case MAC0 ... MAC0+5: ++ case MAC0 ... MAC0+4: ++ s->phys[addr - MAC0] = val; ++ break; ++ case MAC0+5: + s->phys[addr - MAC0] = val; ++ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->phys); + break; + case MAC0+6 ... MAC0+7: + /* reserved */ +-- +1.7.1 + diff --git a/SOURCES/kvm-net-update-nic-info-during-device-reset.patch b/SOURCES/kvm-net-update-nic-info-during-device-reset.patch new file mode 100644 index 0000000..bf97259 --- /dev/null +++ b/SOURCES/kvm-net-update-nic-info-during-device-reset.patch @@ -0,0 +1,62 @@ +From c3ceee56d6d43cd234fcc297b802d68a53b3a12a Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Tue, 5 Nov 2013 09:17:39 +0100 +Subject: [PATCH 07/25] net: update nic info during device reset + +RH-Author: Amos Kong +Message-id: <1383643062-1844-2-git-send-email-akong@redhat.com> +Patchwork-id: 55368 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 1/4] net: update nic info during device reset +Bugzilla: 922589 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Alex Williamson +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 922589 + +macaddr is reset during device reset, but nic info +isn't updated, this problem exists in e1000 & rtl8139 + +Signed-off-by: Amos Kong +Acked-by: Michael S. Tsirkin +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 655d3b63b036b70714adbdae685055f1bda0f8f1) +--- + hw/net/e1000.c | 1 + + hw/net/rtl8139.c | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/net/e1000.c | 1 + + hw/net/rtl8139.c | 1 + + 2 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index a813523..d273ef2 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -315,6 +315,7 @@ static void e1000_reset(void *opaque) + d->mac_reg[RA] |= macaddr[i] << (8 * i); + d->mac_reg[RA + 1] |= (i < 2) ? macaddr[i + 4] << (8 * i) : 0; + } ++ qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); + } + + static void +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 8f20ef4..3ff5518 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -1202,6 +1202,7 @@ static void rtl8139_reset(DeviceState *d) + + /* restore MAC address */ + memcpy(s->phys, s->conf.macaddr.a, 6); ++ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->phys); + + /* reset interrupt mask */ + s->IntrStatus = 0; +-- +1.7.1 + diff --git a/SOURCES/kvm-osdep-add-qemu_get_local_state_pathname.patch b/SOURCES/kvm-osdep-add-qemu_get_local_state_pathname.patch new file mode 100644 index 0000000..d620140 --- /dev/null +++ b/SOURCES/kvm-osdep-add-qemu_get_local_state_pathname.patch @@ -0,0 +1,130 @@ +From eb8c85b01be23beabb2b61e8b32a7e20ca0fea17 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:22 +0200 +Subject: [PATCH 01/28] osdep: add qemu_get_local_state_pathname() + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-2-git-send-email-lersek@redhat.com> +Patchwork-id: 52863 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/6] osdep: add qemu_get_local_state_pathname() +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +This function returns ${prefix}/var/RELATIVE_PATHNAME on POSIX-y systems, +and /RELATIVE_PATHNAME on Win32. + +http://msdn.microsoft.com/en-us/library/bb762494.aspx + + [...] This folder is used for application data that is not user + specific. For example, an application can store a spell-check + dictionary, a database of clip art, or a log file in the + CSIDL_COMMON_APPDATA folder. [...] + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael Roth +(cherry picked from commit e2ea3515a9d2d747f91dadf361afcbeb57a71500) +--- + include/qemu/osdep.h | 11 +++++++++++ + util/oslib-posix.c | 9 +++++++++ + util/oslib-win32.c | 22 ++++++++++++++++++++++ + 3 files changed, 42 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/qemu/osdep.h | 11 +++++++++++ + util/oslib-posix.c | 9 +++++++++ + util/oslib-win32.c | 22 ++++++++++++++++++++++ + 3 files changed, 42 insertions(+), 0 deletions(-) + +diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h +index 57d7b1f..26136f1 100644 +--- a/include/qemu/osdep.h ++++ b/include/qemu/osdep.h +@@ -204,4 +204,15 @@ const char *qemu_get_version(void); + void fips_set_state(bool requested); + bool fips_get_state(void); + ++/* Return a dynamically allocated pathname denoting a file or directory that is ++ * appropriate for storing local state. ++ * ++ * @relative_pathname need not start with a directory separator; one will be ++ * added automatically. ++ * ++ * The caller is responsible for releasing the value returned with g_free() ++ * after use. ++ */ ++char *qemu_get_local_state_pathname(const char *relative_pathname); ++ + #endif +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index 631a1de..3dc8b1b 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -47,6 +47,8 @@ extern int daemon(int, int); + # define QEMU_VMALLOC_ALIGN getpagesize() + #endif + ++#include ++ + #include "config-host.h" + #include "sysemu/sysemu.h" + #include "trace.h" +@@ -232,3 +234,10 @@ int qemu_utimens(const char *path, const struct timespec *times) + + return utimes(path, &tv[0]); + } ++ ++char * ++qemu_get_local_state_pathname(const char *relative_pathname) ++{ ++ return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR, ++ relative_pathname); ++} +diff --git a/util/oslib-win32.c b/util/oslib-win32.c +index df2ecbd..961fbf5 100644 +--- a/util/oslib-win32.c ++++ b/util/oslib-win32.c +@@ -26,12 +26,17 @@ + * THE SOFTWARE. + */ + #include ++#include ++#include + #include "config-host.h" + #include "sysemu/sysemu.h" + #include "qemu/main-loop.h" + #include "trace.h" + #include "qemu/sockets.h" + ++/* this must come after including "trace.h" */ ++#include ++ + void *qemu_oom_check(void *ptr) + { + if (ptr == NULL) { +@@ -160,3 +165,20 @@ int qemu_get_thread_id(void) + { + return GetCurrentThreadId(); + } ++ ++char * ++qemu_get_local_state_pathname(const char *relative_pathname) ++{ ++ HRESULT result; ++ char base_path[MAX_PATH+1] = ""; ++ ++ result = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, ++ /* SHGFP_TYPE_CURRENT */ 0, base_path); ++ if (result != S_OK) { ++ /* misconfigured environment */ ++ g_critical("CSIDL_COMMON_APPDATA unavailable: %ld", (long)result); ++ abort(); ++ } ++ return g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", base_path, ++ relative_pathname); ++} +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Don-t-explode-QEMUMachineInitArgs-into-local-vari.patch b/SOURCES/kvm-pc-Don-t-explode-QEMUMachineInitArgs-into-local-vari.patch new file mode 100644 index 0000000..aaa00b5 --- /dev/null +++ b/SOURCES/kvm-pc-Don-t-explode-QEMUMachineInitArgs-into-local-vari.patch @@ -0,0 +1,100 @@ +From 5c9aa8edab3724f6a361c98247949d5588f18620 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:19 +0100 +Subject: [PATCH 19/29] pc: Don't explode QEMUMachineInitArgs into local variables needlessly + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-3-git-send-email-armbru@redhat.com> +Patchwork-id: 55238 +O-Subject: [PATCH 7.0 qemu-kvm 02/11] pc: Don't explode QEMUMachineInitArgs into local variables needlessly +Bugzilla: 994490 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Don't explode when the variable is used just a few times, and never +changed. + +Signed-off-by: Markus Armbruster +Reviewed-by: Laszlo Ersek +Reviewed-by: Eduardo Habkost +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 3b6fb9cab2e64804cdab5a61d1298ffd8b8dff85) + +Conflicts: + hw/i386/pc_q35.c +--- + hw/i386/pc_q35.c | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_q35.c | 22 +++++++++------------- + 1 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 1c4c8a4..99d3a10 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -51,12 +51,6 @@ static bool has_pvpanic = true; + /* PC hardware initialisation */ + static void pc_q35_init(QEMUMachineInitArgs *args) + { +- ram_addr_t ram_size = args->ram_size; +- const char *cpu_model = args->cpu_model; +- const char *kernel_filename = args->kernel_filename; +- const char *kernel_cmdline = args->kernel_cmdline; +- const char *initrd_filename = args->initrd_filename; +- const char *boot_device = args->boot_device; + ram_addr_t below_4g_mem_size, above_4g_mem_size; + Q35PCIHost *q35_host; + PCIBus *host_bus; +@@ -82,17 +76,17 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + object_property_add_child(qdev_get_machine(), "icc-bridge", + OBJECT(icc_bridge), NULL); + +- pc_cpus_init(cpu_model, icc_bridge); ++ pc_cpus_init(args->cpu_model, icc_bridge); + pc_acpi_init("q35-acpi-dsdt.aml"); + + kvmclock_create(); + +- if (ram_size >= 0xb0000000) { +- above_4g_mem_size = ram_size - 0xb0000000; ++ if (args->ram_size >= 0xb0000000) { ++ above_4g_mem_size = args->ram_size - 0xb0000000; + below_4g_mem_size = 0xb0000000; + } else { + above_4g_mem_size = 0; +- below_4g_mem_size = ram_size; ++ below_4g_mem_size = args->ram_size; + } + + /* pci enabled */ +@@ -107,8 +101,10 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + + /* allocate ram and load rom/bios */ + if (!xen_enabled()) { +- pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline, +- initrd_filename, below_4g_mem_size, above_4g_mem_size, ++ pc_memory_init(get_system_memory(), ++ args->kernel_filename, args->kernel_cmdline, ++ args->initrd_filename, ++ below_4g_mem_size, above_4g_mem_size, + rom_memory, &ram_memory); + } + +@@ -193,7 +189,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + 0xb100), + 8, NULL, 0); + +- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, ++ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_device, + floppy, idebus[0], idebus[1], rtc_state); + + /* the rest devices to which pci devfn is automatically assigned */ +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Don-t-prematurely-explode-QEMUMachineInitArgs.patch b/SOURCES/kvm-pc-Don-t-prematurely-explode-QEMUMachineInitArgs.patch new file mode 100644 index 0000000..e24443e --- /dev/null +++ b/SOURCES/kvm-pc-Don-t-prematurely-explode-QEMUMachineInitArgs.patch @@ -0,0 +1,178 @@ +From c12c0b02880f4162cc237f11407532375882b941 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:18 +0100 +Subject: [PATCH 18/29] pc: Don't prematurely explode QEMUMachineInitArgs + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55237 +O-Subject: [PATCH 7.0 qemu-kvm 01/11] pc: Don't prematurely explode QEMUMachineInitArgs +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Don't explode QEMUMachineInitArgs before passing it to pc_init1(). + +Signed-off-by: Markus Armbruster +Reviewed-by: Laszlo Ersek +Reviewed-by: Eduardo Habkost +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 5650f5f48bfe2a684138505aae008dc4440202f1) + +Conflicts: + hw/i386/pc_piix.c + +Maintainer's note: Fixed incorrect change in c_init_pci_no_kvmclock() + +--- + hw/i386/pc_piix.c | 66 ++++++++++++++----------------------------------------- + 1 file changed, 16 insertions(+), 50 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 65 +++++++++++++---------------------------------------- + 1 files changed, 16 insertions(+), 49 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 3a8418e..65f7f3a 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -59,14 +59,9 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; + static bool has_pvpanic = true; + + /* PC hardware initialisation */ +-static void pc_init1(MemoryRegion *system_memory, ++static void pc_init1(QEMUMachineInitArgs *args, ++ MemoryRegion *system_memory, + MemoryRegion *system_io, +- ram_addr_t ram_size, +- const char *boot_device, +- const char *kernel_filename, +- const char *kernel_cmdline, +- const char *initrd_filename, +- const char *cpu_model, + int pci_enabled, + int kvmclock_enabled) + { +@@ -95,18 +90,18 @@ static void pc_init1(MemoryRegion *system_memory, + object_property_add_child(qdev_get_machine(), "icc-bridge", + OBJECT(icc_bridge), NULL); + +- pc_cpus_init(cpu_model, icc_bridge); ++ pc_cpus_init(args->cpu_model, icc_bridge); + + if (kvmclock_enabled) { + kvmclock_create(); + } + +- if (ram_size >= QEMU_BELOW_4G_RAM_END ) { +- above_4g_mem_size = ram_size - QEMU_BELOW_4G_RAM_END; ++ if (args->ram_size >= QEMU_BELOW_4G_RAM_END ) { ++ above_4g_mem_size = args->ram_size - QEMU_BELOW_4G_RAM_END; + below_4g_mem_size = QEMU_BELOW_4G_RAM_END; + } else { + above_4g_mem_size = 0; +- below_4g_mem_size = ram_size; ++ below_4g_mem_size = args->ram_size; + } + + if (pci_enabled) { +@@ -121,7 +116,8 @@ static void pc_init1(MemoryRegion *system_memory, + /* allocate ram and load rom/bios */ + if (!xen_enabled()) { + fw_cfg = pc_memory_init(system_memory, +- kernel_filename, kernel_cmdline, initrd_filename, ++ args->kernel_filename, args->kernel_cmdline, ++ args->initrd_filename, + below_4g_mem_size, above_4g_mem_size, + rom_memory, &ram_memory); + } +@@ -137,7 +133,7 @@ static void pc_init1(MemoryRegion *system_memory, + + if (pci_enabled) { + pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, +- system_memory, system_io, ram_size, ++ system_memory, system_io, args->ram_size, + below_4g_mem_size, + 0x100000000ULL - below_4g_mem_size, + 0x100000000ULL + above_4g_mem_size, +@@ -202,7 +198,7 @@ static void pc_init1(MemoryRegion *system_memory, + } + } + +- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, ++ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_device, + floppy, idebus[0], idebus[1], rtc_state); + + if (pci_enabled && usb_enabled(false)) { +@@ -232,17 +228,7 @@ static void pc_init1(MemoryRegion *system_memory, + + static void pc_init_pci(QEMUMachineInitArgs *args) + { +- ram_addr_t ram_size = args->ram_size; +- const char *cpu_model = args->cpu_model; +- const char *kernel_filename = args->kernel_filename; +- const char *kernel_cmdline = args->kernel_cmdline; +- const char *initrd_filename = args->initrd_filename; +- const char *boot_device = args->boot_device; +- pc_init1(get_system_memory(), +- get_system_io(), +- ram_size, boot_device, +- kernel_filename, kernel_cmdline, +- initrd_filename, cpu_model, 1, 1); ++ pc_init1(args, get_system_memory(), get_system_io(), 1, 1); + } + + #if 0 /* Disabled for Red Hat Enterprise Linux */ +@@ -283,40 +269,21 @@ static void pc_init_pci_1_0(QEMUMachineInitArgs *args) + /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */ + static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) + { +- ram_addr_t ram_size = args->ram_size; +- const char *cpu_model = args->cpu_model; +- const char *kernel_filename = args->kernel_filename; +- const char *kernel_cmdline = args->kernel_cmdline; +- const char *initrd_filename = args->initrd_filename; +- const char *boot_device = args->boot_device; + has_pvpanic = false; + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- pc_init1(get_system_memory(), +- get_system_io(), +- ram_size, boot_device, +- kernel_filename, kernel_cmdline, +- initrd_filename, cpu_model, 1, 0); ++ pc_init1(args, get_system_memory(), get_system_io(), 1, 0); + } + + static void pc_init_isa(QEMUMachineInitArgs *args) + { +- ram_addr_t ram_size = args->ram_size; +- const char *cpu_model = args->cpu_model; +- const char *kernel_filename = args->kernel_filename; +- const char *kernel_cmdline = args->kernel_cmdline; +- const char *initrd_filename = args->initrd_filename; +- const char *boot_device = args->boot_device; + has_pvpanic = false; +- if (cpu_model == NULL) +- cpu_model = "486"; ++ if (!args->cpu_model) { ++ args->cpu_model = "486"; ++ } + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- pc_init1(get_system_memory(), +- get_system_io(), +- ram_size, boot_device, +- kernel_filename, kernel_cmdline, +- initrd_filename, cpu_model, 0, 1); ++ pc_init1(args, get_system_memory(), get_system_io(), 0, 1); + } + + #ifdef CONFIG_XEN +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Haswell-doesn-t-have-rdtscp-on-rhel6.x.patch b/SOURCES/kvm-pc-Haswell-doesn-t-have-rdtscp-on-rhel6.x.patch new file mode 100644 index 0000000..0c5cd7f --- /dev/null +++ b/SOURCES/kvm-pc-Haswell-doesn-t-have-rdtscp-on-rhel6.x.patch @@ -0,0 +1,46 @@ +From da27199bd3f4ec0e616330bcf7b4fb818eae50ab Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:52 +0200 +Subject: [PATCH 24/28] pc: Haswell doesn't have rdtscp on rhel6.x + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-8-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53615 +O-Subject: [RHEL7 PATCH 7/7] pc: Haswell doesn't have rdtscp on rhel6.x +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + +This adds compat code to disable rdtscp on the rhel6.x machine-types, to +match the features found on RHEL-6. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index fb5256e..da7701c 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -877,6 +877,8 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + 0); + x86_cpu_compat_set_features("SandyBridge", FEAT_8000_0001_EDX, + 0, CPUID_EXT2_RDTSCP); ++ x86_cpu_compat_set_features("Haswell", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); + pc_init_rhel700(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Make-no-fd-bootchk-stick-across-boot-order-change.patch b/SOURCES/kvm-pc-Make-no-fd-bootchk-stick-across-boot-order-change.patch new file mode 100644 index 0000000..57d190c --- /dev/null +++ b/SOURCES/kvm-pc-Make-no-fd-bootchk-stick-across-boot-order-change.patch @@ -0,0 +1,87 @@ +From 6ddf29f50854ed657ee27241cbd0bb7c2b4ae4b7 Mon Sep 17 00:00:00 2001 +Message-Id: <6ddf29f50854ed657ee27241cbd0bb7c2b4ae4b7.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:15 +0200 +Subject: [PATCH 05/14] pc: Make -no-fd-bootchk stick across boot order + changes + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-6-git-send-email-armbru@redhat.com> +Patchwork-id: 54564 +O-Subject: [PATCH 7.0 qemu-kvm 05/10] pc: Make -no-fd-bootchk stick across boot order changes +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Option -no-fd-bootchk asks the BIOS to attempt booting from a floppy +even when the boot sector signature isn't there, by setting a bit in +RTC CMOS. It was added back in 2006 (commit 52ca8d6a). + +Two years later, commit 0ecdffbb added monitor command boot_set. +Implemented by new function pc_boot_set(). It unconditionally clears +the floppy signature bit in CMOS. + +Commit e0f084bf added -boot option once to automatically change the +boot order on first reset. Reuses pc_boot_set(), thus also clears the +floppy signature bit. Commit d9346e81 took care to preserve this +behavior. + +Thus, -no-fd-bootchk applies to any number of boots. Except it +applies just to the first boot with -boot once, and never after +boot_set. Weird. Make it stick instead: set the bit according to +-no-fd-bootchk in pc_boot_set(). + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-6-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit e1123015a50abf44f9daa9495f40eeaaf4c9bb98) +--- + hw/i386/pc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Signed-off-by: Michal Novotny +--- + hw/i386/pc.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 71b7a26..3c77040 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -266,7 +266,7 @@ static int boot_device2nibble(char boot_device) + return 0; + } + +-static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk) ++static int set_boot_dev(ISADevice *s, const char *boot_device) + { + #define PC_MAX_BOOT_DEVICES 3 + int nbds, bds[3] = { 0, }; +@@ -292,7 +292,7 @@ static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk) + + static int pc_boot_set(void *opaque, const char *boot_device) + { +- return set_boot_dev(opaque, boot_device, 0); ++ return set_boot_dev(opaque, boot_device); + } + + typedef struct pc_cmos_init_late_arg { +@@ -407,8 +407,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, + cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added; + qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier); + +- /* set boot devices, and disable floppy signature check if requested */ +- if (set_boot_dev(s, boot_device, fd_bootchk)) { ++ if (set_boot_dev(s, boot_device)) { + exit(1); + } + +-- +1.7.11.7 + diff --git a/SOURCES/kvm-pc-RHEL-6-don-t-have-RDTSCP.patch b/SOURCES/kvm-pc-RHEL-6-don-t-have-RDTSCP.patch new file mode 100644 index 0000000..272a1e2 --- /dev/null +++ b/SOURCES/kvm-pc-RHEL-6-don-t-have-RDTSCP.patch @@ -0,0 +1,57 @@ +From 4806c6609872f4b642da379b7d7e54e9b0f9c09f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Mon, 16 Sep 2013 20:39:57 +0200 +Subject: [PATCH 08/25] pc: RHEL-6 don't have RDTSCP + +RH-Author: Eduardo Habkost +Message-id: <1379363997-11783-5-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54399 +O-Subject: [RHEL7 PATCH 4/4] pc: RHEL-6 don't have RDTSCP +Bugzilla: 918907 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + (RHEL-6-only quirk that is not going to be included upstream) +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6290888 + +The phenom and Opteron_G[123] CPU models don't have RDTSCP enabled on +RHEL-6, so we have to explicitly disable it on pc_init_rhel650() to keep +compatibility. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 10 ++++++++++ + 1 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index eb3a07d..06e9eb8 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -895,6 +895,16 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + x86_cpu_compat_set_features("Opteron_G1", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Opteron_G2", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Opteron_G3", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ ++ x86_cpu_compat_set_features("phenom", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); ++ x86_cpu_compat_set_features("Opteron_G1", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); ++ x86_cpu_compat_set_features("Opteron_G2", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); ++ x86_cpu_compat_set_features("Opteron_G3", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); ++ + pc_init_rhel700(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-RHEL-6-had-x2apic-set-on-Opteron_G-123.patch b/SOURCES/kvm-pc-RHEL-6-had-x2apic-set-on-Opteron_G-123.patch new file mode 100644 index 0000000..2eace70 --- /dev/null +++ b/SOURCES/kvm-pc-RHEL-6-had-x2apic-set-on-Opteron_G-123.patch @@ -0,0 +1,53 @@ +From 9913f2856aeeaa05b7b5e3188865901f79ea2166 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Mon, 16 Sep 2013 20:39:56 +0200 +Subject: [PATCH 07/25] pc: RHEL-6 had x2apic set on Opteron_G[123] + +RH-Author: Eduardo Habkost +Message-id: <1379363997-11783-4-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54401 +O-Subject: [RHEL7 PATCH 3/4] pc: RHEL-6 had x2apic set on Opteron_G[123] +Bugzilla: 918907 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +From: Eduardo Habkost + +Bugzilla: 918907 +Upstream status: not applicable + (RHEL-6-only quirk that is not going to be included upstream) +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6290888 + +The Opteron_G[123] CPU models had x2apic set since they were first added +to RHEL-6, but they don't have it set upstream. We need to explicitly +set it on pc_init_rhel650() to keep compatibility. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 6fe6ba0..eb3a07d 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -891,6 +891,10 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + 0, CPUID_EXT2_RDTSCP); + x86_cpu_compat_set_features("Haswell", FEAT_8000_0001_EDX, + 0, CPUID_EXT2_RDTSCP); ++ ++ x86_cpu_compat_set_features("Opteron_G1", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Opteron_G2", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Opteron_G3", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + pc_init_rhel700(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Remove-PCLMULQDQ-from-Westmere-on-rhel6.x-machine.patch b/SOURCES/kvm-pc-Remove-PCLMULQDQ-from-Westmere-on-rhel6.x-machine.patch new file mode 100644 index 0000000..7e12d2e --- /dev/null +++ b/SOURCES/kvm-pc-Remove-PCLMULQDQ-from-Westmere-on-rhel6.x-machine.patch @@ -0,0 +1,50 @@ +From 6d3c6d947de6e5721d8a011789909f55ffef833f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:50 +0200 +Subject: [PATCH 22/28] pc: Remove PCLMULQDQ from Westmere on rhel6.x machine-types + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-6-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53612 +O-Subject: [RHEL7 PATCH 5/7] pc: Remove PCLMULQDQ from Westmere on rhel6.x machine-types +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: commit 56383703c060777fd01aaf8d63d5f46d660e9fb9 + +commit 41cb383f42d0cb51d8e3e25e3ecebc954dd4196f made a guest-visible +change by adding the PCLMULQDQ bit to Westmere without adding +compatibility code to keep the ABI for older machine-types. + +Add the corresponding compat code to the rhel6.x machine-types (like it +was done on upstream commit 56383703c060777fd01aaf8d63d5f46d660e9fb9 for +pc-1.4). + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index d5dc04d..846e2ce 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -868,6 +868,7 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + x86_cpu_compat_set_features("Penryn", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Nehalem", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ); + x86_cpu_compat_set_features("Westmere", FEAT_8000_0001_EDX, + CPUID_EXT2_FXSR | CPUID_EXT2_MMX | CPUID_EXT2_PAT | + CPUID_EXT2_CMOV | CPUID_EXT2_PGE | CPUID_EXT2_APIC | +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-Remove-incorrect-rhel6.x-compat-model-value-for-C.patch b/SOURCES/kvm-pc-Remove-incorrect-rhel6.x-compat-model-value-for-C.patch new file mode 100644 index 0000000..2eb5ca6 --- /dev/null +++ b/SOURCES/kvm-pc-Remove-incorrect-rhel6.x-compat-model-value-for-C.patch @@ -0,0 +1,67 @@ +From c24fbe335c22ced933edb7d72f03adaf64000056 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:47 +0200 +Subject: [PATCH 19/28] pc: Remove incorrect rhel6.x compat "model" value for Conroe/Penryn/Nehalem + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-3-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53610 +O-Subject: [RHEL7 PATCH 2/7] pc: Remove incorrect rhel6.x compat "model" value for Conroe/Penryn/Nehalem +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + +The series that introduced the rhel6.x machine-types added compat +"model" values for Conroe, Penryn and Nehalem that were copied from +PC_COMPAT_1_5 but are not applicable to rhel6.x, as the CPU models had +the correct model value since RHEL-6.0 (see RHEL-6 commit +9a2e04fed8d1c4b44c4122b211e236a36a036cc7). + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 12 ------------ + 1 file changed, 12 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 12 ------------ + 1 files changed, 0 insertions(+), 12 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 0dc52c4..a11a4b0 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -910,26 +910,14 @@ static QEMUMachine pc_machine_rhel640 = { + PC_RHEL6_4_COMPAT,\ + {\ + .driver = "Conroe-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "Penryn-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Penryn-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ + .driver = "Nehalem-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Nehalem-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ + },{\ +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-SandyBridge-rhel6.x-compat-fixes.patch b/SOURCES/kvm-pc-SandyBridge-rhel6.x-compat-fixes.patch new file mode 100644 index 0000000..5af541d --- /dev/null +++ b/SOURCES/kvm-pc-SandyBridge-rhel6.x-compat-fixes.patch @@ -0,0 +1,59 @@ +From f28b055b5d576b9e5e87aa18bf655b53eff1571c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:51 +0200 +Subject: [PATCH 23/28] pc: SandyBridge rhel6.x compat fixes + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-7-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53614 +O-Subject: [RHEL7 PATCH 6/7] pc: SandyBridge rhel6.x compat fixes +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + +This patch implements the following changes, to match the SandyBridge +CPU features on RHEL-6: + + * rhel6.3.0 and older don't have tsc-deadline on SandyBridge + (commit 10ce057) + * rhel6.5.0 and older don't have rdtscp on SandyBridge + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 846e2ce..fb5256e 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -875,6 +875,8 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | + CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, + 0); ++ x86_cpu_compat_set_features("SandyBridge", FEAT_8000_0001_EDX, ++ 0, CPUID_EXT2_RDTSCP); + pc_init_rhel700(args); + } + +@@ -961,6 +963,8 @@ static void pc_init_rhel630(QEMUMachineInitArgs *args) + { + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); ++ x86_cpu_compat_set_features("SandyBridge", FEAT_1_ECX, ++ 0, CPUID_EXT_TSC_DEADLINE_TIMER); + pc_init_rhel640(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-drop-external-DSDT-loading.patch b/SOURCES/kvm-pc-drop-external-DSDT-loading.patch new file mode 100644 index 0000000..36dc5ce --- /dev/null +++ b/SOURCES/kvm-pc-drop-external-DSDT-loading.patch @@ -0,0 +1,45 @@ +From 9071e5a73e65f8032c0fbf283b1dbdfa67b0c617 Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:15 +0200 +Subject: [PATCH 20/25] pc: drop external DSDT loading + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-11-git-send-email-owasserm@redhat.com> +Patchwork-id: 54806 +O-Subject: [RHEL7.0 qemu-kvm v2 10/10] pc: drop external DSDT loading +Bugzilla: 921465 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela +RH-Acked-by: Paolo Bonzini + +From: Anthony Liguori + +This breaks migration and is unneeded with modern SeaBIOS. + +Signed-off-by: Anthony Liguori +Message-id: 1376316104-11269-1-git-send-email-aliguori@us.ibm.com +(cherry picked from commit 9fb7aaaf4c58c9108327f0ae4766087e3e496b47) +--- + hw/i386/pc_piix.c | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 06e9eb8..af1f602 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -96,7 +96,6 @@ static void pc_init1(MemoryRegion *system_memory, + OBJECT(icc_bridge), NULL); + + pc_cpus_init(cpu_model, icc_bridge); +- pc_acpi_init("acpi-dsdt.aml"); + + if (kvmclock_enabled) { + kvmclock_create(); +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-rhel6-doesn-t-have-APIC-on-pentium-CPU-models.patch b/SOURCES/kvm-pc-rhel6-doesn-t-have-APIC-on-pentium-CPU-models.patch new file mode 100644 index 0000000..6942e85 --- /dev/null +++ b/SOURCES/kvm-pc-rhel6-doesn-t-have-APIC-on-pentium-CPU-models.patch @@ -0,0 +1,55 @@ +From ddcaa23c15a4881a882686961d99fc26abb45357 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Mon, 16 Sep 2013 20:39:55 +0200 +Subject: [PATCH 06/25] pc: rhel6 doesn't have APIC on pentium* CPU models + +RH-Author: Eduardo Habkost +Message-id: <1379363997-11783-3-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54400 +O-Subject: [RHEL7 PATCH 2/4] pc: rhel6 doesn't have APIC on pentium* CPU models +Bugzilla: 918907 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +From: Eduardo Habkost + +Bugzilla: 918907 +Upstream status: not applicable + (pc-0.12 already have CPUID_APIC enabled for almost 4 years) +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6290888 + +QEMU v0.13 and newer has CPUID_APIC set on pentium, pentium2, and +pentium3 CPU models[1], but v0.12 (and RHEL-6) don't have it. We need to +disable the flag on pc_init_rhel650() to keep compatibility. + +[1] Upstream commit c84bd4f104098861e162be848a00d64c1fa76ed4 + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 39be127..6fe6ba0 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -872,6 +872,10 @@ static QEMUMachine pc_machine_rhel700 = { + + static void pc_init_rhel650(QEMUMachineInitArgs *args) + { ++ x86_cpu_compat_set_features("pentium", FEAT_1_EDX, 0, CPUID_APIC); ++ x86_cpu_compat_set_features("pentium2", FEAT_1_EDX, 0, CPUID_APIC); ++ x86_cpu_compat_set_features("pentium3", FEAT_1_EDX, 0, CPUID_APIC); ++ + x86_cpu_compat_set_features("Conroe", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Penryn", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Nehalem", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-rhel6.x-has-x2apic-present-on-Conroe-Penryn-Nehal.patch b/SOURCES/kvm-pc-rhel6.x-has-x2apic-present-on-Conroe-Penryn-Nehal.patch new file mode 100644 index 0000000..7d719de --- /dev/null +++ b/SOURCES/kvm-pc-rhel6.x-has-x2apic-present-on-Conroe-Penryn-Nehal.patch @@ -0,0 +1,49 @@ +From 7d9e001ea97e762782e6875d220cc50269c1005f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:48 +0200 +Subject: [PATCH 20/28] pc: rhel6.x has x2apic present on Conroe/Penryn/Nehalem CPU models + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-4-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53613 +O-Subject: [RHEL7 PATCH 3/7] pc: rhel6.x has x2apic present on Conroe/Penryn/Nehalem CPU models +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + +The Conroe/Penryn/Nehalem CPU models all have x2apic enabled on rhel6.x +(added by RHEL-6 commit 19ab65a663cfdfa8365f3ec324af6b0ab26be5a1). Add +compat bits to make sure they are set on the rhel6.x machine-types. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index a11a4b0..c5d82ab 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -864,6 +864,10 @@ static QEMUMachine pc_machine_rhel700 = { + + static void pc_init_rhel650(QEMUMachineInitArgs *args) + { ++ x86_cpu_compat_set_features("Conroe", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Penryn", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Nehalem", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + pc_init_rhel700(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-set-compat-CPUID-0x80000001-.EDX-bits-on-Westmere.patch b/SOURCES/kvm-pc-set-compat-CPUID-0x80000001-.EDX-bits-on-Westmere.patch new file mode 100644 index 0000000..a6045c7 --- /dev/null +++ b/SOURCES/kvm-pc-set-compat-CPUID-0x80000001-.EDX-bits-on-Westmere.patch @@ -0,0 +1,53 @@ +From 78fbb36235f35484e0ae0a124269b35288dd472b Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:49 +0200 +Subject: [PATCH 21/28] pc: set compat CPUID[0x80000001].EDX bits on Westmere for rhel6.x + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-5-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53611 +O-Subject: [RHEL7 PATCH 4/7] pc: set compat CPUID[0x80000001].EDX bits on Westmere for rhel6.x +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + +On RHEL-6 the Westmere CPU model has many CPU feature alias bits +incorrectly set on CPUID[0x80000001].EDX. This is a RHEL-6 bug (that +doesn't cause problems because those bits are documented as reserved on +Intel CPUs), but we need to keep exactly the same bits for compatibility +on the rhel6.x machine-types. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index c5d82ab..d5dc04d 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -868,6 +868,12 @@ static void pc_init_rhel650(QEMUMachineInitArgs *args) + x86_cpu_compat_set_features("Penryn", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Nehalem", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); + x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, CPUID_EXT_X2APIC, 0); ++ x86_cpu_compat_set_features("Westmere", FEAT_8000_0001_EDX, ++ CPUID_EXT2_FXSR | CPUID_EXT2_MMX | CPUID_EXT2_PAT | ++ CPUID_EXT2_CMOV | CPUID_EXT2_PGE | CPUID_EXT2_APIC | ++ CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | ++ CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, ++ 0); + pc_init_rhel700(args); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pc-set-compat-pmu-property-for-rhel6-x-machine-types.patch b/SOURCES/kvm-pc-set-compat-pmu-property-for-rhel6-x-machine-types.patch new file mode 100644 index 0000000..2c2095c --- /dev/null +++ b/SOURCES/kvm-pc-set-compat-pmu-property-for-rhel6-x-machine-types.patch @@ -0,0 +1,55 @@ +From 0bc3adc3b0a24625b1f8217abc1a50d7ce741191 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Fri, 2 Aug 2013 14:08:53 +0200 +Subject: pc: set compat "pmu" property for rhel6.x machine-types + +RH-Author: Eduardo Habkost +Message-id: <1375452533-12507-4-git-send-email-ehabkost@redhat.com> +Patchwork-id: 52934 +O-Subject: [RHEL-7 PATCH 3/3] pc: set compat "pmu" property for rhel6.x machine-types +Bugzilla: 853101 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Gleb Natapov + +Bugzilla: 853101 +Upstream status: not applicable + +This adds compatibility values to the rhel6.* machine-types for the +"pmu" property on X86CPU: + + * rhel6.2 and older doesn't have vPMU support + * rhel6.3 has the broken passthrough-mode vPMU enabled + * rhel6.4 and newer have vPMU disabled by default + +Signed-off-by: Eduardo Habkost + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index e1bedec..bc67633 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -942,6 +942,10 @@ static QEMUMachine pc_machine_rhel640 = { + .driver = "virtio-scsi-pci",\ + .property = "param_change",\ + .value = "off",\ ++ },{\ ++ .driver = TYPE_X86_CPU,\ ++ .property = "pmu",\ ++ .value = "on",\ + } + + static void pc_init_rhel630(QEMUMachineInitArgs *args) +@@ -964,7 +968,12 @@ static QEMUMachine pc_machine_rhel630 = { + }; + + #define PC_RHEL6_2_COMPAT \ +- PC_RHEL6_3_COMPAT ++ PC_RHEL6_3_COMPAT,\ ++ {\ ++ .driver = TYPE_X86_CPU,\ ++ .property = "pmu",\ ++ .value = "off",\ ++ } + + static void pc_init_rhel620(QEMUMachineInitArgs *args) + { diff --git a/SOURCES/kvm-pc-set-level-xlevel-correctly-on-486-qemu32-CPU-mode.patch b/SOURCES/kvm-pc-set-level-xlevel-correctly-on-486-qemu32-CPU-mode.patch new file mode 100644 index 0000000..ce63b4f --- /dev/null +++ b/SOURCES/kvm-pc-set-level-xlevel-correctly-on-486-qemu32-CPU-mode.patch @@ -0,0 +1,54 @@ +From 235601c37ce0dd3c42906d29b20c4f32b15a1b4f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 20 Aug 2013 15:09:46 +0200 +Subject: [PATCH 18/28] pc: set level/xlevel correctly on 486/qemu32 CPU models for rhel6.x + +RH-Author: Eduardo Habkost +Message-id: <1377011392-9336-2-git-send-email-ehabkost@redhat.com> +Patchwork-id: 53609 +O-Subject: [RHEL7 PATCH 1/7] pc: set level/xlevel correctly on 486/qemu32 CPU models for rhel6.x +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 918907 +Upstream status: not applicable + (Upstream have the new xlevel on all machine-types since v0.13) + +Upstream commit 58012d66dc7323f48e9bad3be6d65a50ed3d76bc changed xlevel +on the "qemu32" CPU model and level on "486", but we need to keep a +compatible value on the rhel6.x machine-types. + +Signed-off-by: Eduardo Habkost +--- + hw/i386/pc_piix.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 0f63290..0dc52c4 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -852,6 +852,14 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "AC97",\ + .property = "use_broken_id",\ + .value = stringify(1),\ ++ },{\ ++ .driver = "qemu32-" TYPE_X86_CPU,\ ++ .property = "xlevel",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "486-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(0),\ + } + + static void pc_init_rhel650(QEMUMachineInitArgs *args) +-- +1.7.1 + diff --git a/SOURCES/kvm-pc_piix-disable-CPUID_SEP-for-6-4-0-machine-types-and-below.patch b/SOURCES/kvm-pc_piix-disable-CPUID_SEP-for-6-4-0-machine-types-and-below.patch new file mode 100644 index 0000000..73780dd --- /dev/null +++ b/SOURCES/kvm-pc_piix-disable-CPUID_SEP-for-6-4-0-machine-types-and-below.patch @@ -0,0 +1,41 @@ +From dd1eabf6ba0b2a42b034f0918bf0370307983709 Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Wed, 7 Aug 2013 17:28:00 +0200 +Subject: pc_piix: disable CPUID_SEP for 6.4.0 machine types and below + +RH-Author: Bandan Das +Message-id: +Patchwork-id: 53052 +O-Subject: [PATCH RHEL-7 qemu-kvm v2] pc_piix: disable CPUID_SEP for 6.4.0 machine types and below +Bugzilla: 960216 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Laszlo Ersek + +Bugzilla : 960216 +Brew : https://brewweb.devel.redhat.com/taskinfo?taskID=6140166 + +With c88f862d9 the SEP flag was disabled for RHEL 6.4 and below +machine types due to a kernel bug. 3af51f9^..8f38a22 enabled it +back again for RHEL 6.5 machine type. This change implements +this rhel 6 compatibility behavior + +Implementation differences : Simply call x86_cpu_compat_set_features, +NULL signifies all applicable CPU models + +v2 : specify correct comment range for rhel 6 commits + +Signed-off-by: Bandan Das + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index bc67633..9e03e52 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -881,6 +881,7 @@ static QEMUMachine pc_machine_rhel650 = { + static void pc_init_rhel640(QEMUMachineInitArgs *args) + { + has_pvpanic = false; ++ x86_cpu_compat_set_features(NULL, FEAT_1_EDX, 0, CPUID_SEP); + pc_init_rhel650(args); + } + diff --git a/SOURCES/kvm-pc_piix-disable-mixer-for-6.4.0-machine-types-and-be.patch b/SOURCES/kvm-pc_piix-disable-mixer-for-6.4.0-machine-types-and-be.patch new file mode 100644 index 0000000..b16f171 --- /dev/null +++ b/SOURCES/kvm-pc_piix-disable-mixer-for-6.4.0-machine-types-and-be.patch @@ -0,0 +1,50 @@ +From adbdd4efafb5aae64def7fb8ae78a565d239039f Mon Sep 17 00:00:00 2001 +From: Bandan Das +Date: Tue, 15 Oct 2013 17:11:01 +0200 +Subject: [PATCH 24/25] pc_piix: disable mixer for 6.4.0 machine types and below + +RH-Author: Bandan Das +Message-id: <1381857067-9399-5-git-send-email-bsd@redhat.com> +Patchwork-id: 54952 +O-Subject: [PATCH RHEL-7 qemu-kvm v3 4/5] pc_piix: disable mixer for 6.4.0 machine types and below +Bugzilla: 954195 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Markus Armbruster + +Signed-off-by: Bandan Das +--- + hw/i386/pc_piix.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 12 ++++++++++++ + 1 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index af1f602..3f5b913 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -925,6 +925,18 @@ static QEMUMachine pc_machine_rhel650 = { + .driver = "virtio-scsi-pci",\ + .property = "vectors",\ + .value = stringify(2),\ ++ },{\ ++ .driver = "hda-micro",\ ++ .property = "mixer",\ ++ .value = "off",\ ++ },{\ ++ .driver = "hda-duplex",\ ++ .property = "mixer",\ ++ .value = "off",\ ++ },{\ ++ .driver = "hda-output",\ ++ .property = "mixer",\ ++ .value = "off",\ + } + + static void pc_init_rhel640(QEMUMachineInitArgs *args) +-- +1.7.1 + diff --git a/SOURCES/kvm-pc_sysfw-Fix-ISA-BIOS-init-for-ridiculously-big-flas.patch b/SOURCES/kvm-pc_sysfw-Fix-ISA-BIOS-init-for-ridiculously-big-flas.patch new file mode 100644 index 0000000..d7badde --- /dev/null +++ b/SOURCES/kvm-pc_sysfw-Fix-ISA-BIOS-init-for-ridiculously-big-flas.patch @@ -0,0 +1,54 @@ +From 502442eae625ab550ec2f3b7cb4086f84b6fdb73 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 18 Sep 2013 09:31:09 +0200 +Subject: [PATCH 25/29] pc_sysfw: Fix ISA BIOS init for ridiculously big flash + +RH-Author: Markus Armbruster +Message-id: <1379496669-22778-9-git-send-email-armbru@redhat.com> +Patchwork-id: 54427 +O-Subject: [PATCH 7.0 qemu-kvm 8/8] pc_sysfw: Fix ISA BIOS init for ridiculously big flash +Bugzilla: 1009328 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +pc_isa_bios_init() suffers integer overflow for flash larger than +INT_MAX. + +Signed-off-by: Markus Armbruster +Acked-by: Laszlo Ersek +Acked-by: Stefano Stabellini +Acked-by: Christian Borntraeger +Message-id: 1375276272-15988-9-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 7f87af39dc786a979e7ebba338d0781e366060ed) +--- + hw/block/pc_sysfw.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/block/pc_sysfw.c | 5 +---- + 1 files changed, 1 insertions(+), 4 deletions(-) + +diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c +index 2bbedc9..4e3e6b6 100644 +--- a/hw/block/pc_sysfw.c ++++ b/hw/block/pc_sysfw.c +@@ -54,10 +54,7 @@ static void pc_isa_bios_init(MemoryRegion *rom_memory, + flash_size = memory_region_size(flash_mem); + + /* map the last 128KB of the BIOS in ISA space */ +- isa_bios_size = flash_size; +- if (isa_bios_size > (128 * 1024)) { +- isa_bios_size = 128 * 1024; +- } ++ isa_bios_size = MIN(flash_size, 128 * 1024); + isa_bios = g_malloc(sizeof(*isa_bios)); + memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size); + vmstate_register_ram_global(isa_bios); +-- +1.7.1 + diff --git a/SOURCES/kvm-pci-add-VMSTATE_MSIX.patch b/SOURCES/kvm-pci-add-VMSTATE_MSIX.patch new file mode 100644 index 0000000..64d5f58 --- /dev/null +++ b/SOURCES/kvm-pci-add-VMSTATE_MSIX.patch @@ -0,0 +1,95 @@ +From 3420a9a7d1765a77f5a03e38c0ec6b4b69419e6a Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:22:44 +0200 +Subject: [PATCH 13/28] pci: add VMSTATE_MSIX + +RH-Author: Gerd Hoffmann +Message-id: <1375867368-18979-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 53038 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/5] pci: add VMSTATE_MSIX +Bugzilla: 838170 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Orit Wasserman + +Using a trick cut+pasted from vmstate_scsi_device +to wind up msix_save and msix_load. + +Signed-off-by: Gerd Hoffmann +Acked-by: Michael S. Tsirkin +(cherry picked from commit 340b50c759d6b4ef33e514c40afcc799c0d7df7a) +--- + hw/pci/msix.c | 33 +++++++++++++++++++++++++++++++++ + include/hw/pci/msix.h | 11 +++++++++++ + 2 files changed, 44 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/pci/msix.c | 33 +++++++++++++++++++++++++++++++++ + include/hw/pci/msix.h | 11 +++++++++++ + 2 files changed, 44 insertions(+), 0 deletions(-) + +diff --git a/hw/pci/msix.c b/hw/pci/msix.c +index e231a0d..6da75ec 100644 +--- a/hw/pci/msix.c ++++ b/hw/pci/msix.c +@@ -569,3 +569,36 @@ void msix_unset_vector_notifiers(PCIDevice *dev) + dev->msix_vector_release_notifier = NULL; + dev->msix_vector_poll_notifier = NULL; + } ++ ++static void put_msix_state(QEMUFile *f, void *pv, size_t size) ++{ ++ msix_save(pv, f); ++} ++ ++static int get_msix_state(QEMUFile *f, void *pv, size_t size) ++{ ++ msix_load(pv, f); ++ return 0; ++} ++ ++static VMStateInfo vmstate_info_msix = { ++ .name = "msix state", ++ .get = get_msix_state, ++ .put = put_msix_state, ++}; ++ ++const VMStateDescription vmstate_msix = { ++ .name = "msix", ++ .fields = (VMStateField[]) { ++ { ++ .name = "msix", ++ .version_id = 0, ++ .field_exists = NULL, ++ .size = 0, /* ouch */ ++ .info = &vmstate_info_msix, ++ .flags = VMS_SINGLE, ++ .offset = 0, ++ }, ++ VMSTATE_END_OF_LIST() ++ } ++}; +diff --git a/include/hw/pci/msix.h b/include/hw/pci/msix.h +index e648410..954d82b 100644 +--- a/include/hw/pci/msix.h ++++ b/include/hw/pci/msix.h +@@ -43,4 +43,15 @@ int msix_set_vector_notifiers(PCIDevice *dev, + MSIVectorReleaseNotifier release_notifier, + MSIVectorPollNotifier poll_notifier); + void msix_unset_vector_notifiers(PCIDevice *dev); ++ ++extern const VMStateDescription vmstate_msix; ++ ++#define VMSTATE_MSIX(_field, _state) { \ ++ .name = (stringify(_field)), \ ++ .size = sizeof(PCIDevice), \ ++ .vmsd = &vmstate_msix, \ ++ .flags = VMS_STRUCT, \ ++ .offset = vmstate_offset_value(_state, _field, PCIDevice), \ ++} ++ + #endif +-- +1.7.1 + diff --git a/SOURCES/kvm-pci-assign-Add-MSI-affinity-support.patch b/SOURCES/kvm-pci-assign-Add-MSI-affinity-support.patch new file mode 100644 index 0000000..84dcca2 --- /dev/null +++ b/SOURCES/kvm-pci-assign-Add-MSI-affinity-support.patch @@ -0,0 +1,72 @@ +From 7596bd04d37a608d06cf7a2f589a67d332a21dfb Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 1 Nov 2013 19:50:26 +0100 +Subject: [PATCH 01/25] pci-assign: Add MSI affinity support + +RH-Author: Alex Williamson +Message-id: <20131101195026.25461.63530.stgit@bling.home> +Patchwork-id: 55233 +O-Subject: [RHEL7 qemu-kvm PATCH 1/3] pci-assign: Add MSI affinity support +Bugzilla: 1025877 +RH-Acked-by: Bandan Das +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Orit Wasserman + +Bugzilla: 1025877 +Upstream commit: 3459f01b2d9612070ec23221a4ccb60a41b775ae + +To support guest MSI affinity changes update the MSI message any time +the guest writes to the address or data fields. + +Signed-off-by: Alex Williamson +Acked-by: Michael S. Tsirkin +Message-id: 20130513201840.5430.86331.stgit@bling.home +Signed-off-by: Anthony Liguori +--- + hw/i386/kvm/pci-assign.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvm/pci-assign.c | 18 ++++++++++++++++++ + 1 files changed, 18 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c +index 1684f8c..221a8f7 100644 +--- a/hw/i386/kvm/pci-assign.c ++++ b/hw/i386/kvm/pci-assign.c +@@ -1026,6 +1026,21 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev) + } + } + ++static void assigned_dev_update_msi_msg(PCIDevice *pci_dev) ++{ ++ AssignedDevice *assigned_dev = DO_UPCAST(AssignedDevice, dev, pci_dev); ++ uint8_t ctrl_byte = pci_get_byte(pci_dev->config + pci_dev->msi_cap + ++ PCI_MSI_FLAGS); ++ ++ if (assigned_dev->assigned_irq_type != ASSIGNED_IRQ_MSI || ++ !(ctrl_byte & PCI_MSI_FLAGS_ENABLE)) { ++ return; ++ } ++ ++ kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0], ++ msi_get_message(pci_dev, 0)); ++} ++ + static bool assigned_dev_msix_masked(MSIXTableEntry *entry) + { + return (entry->ctrl & cpu_to_le32(0x1)) != 0; +@@ -1201,6 +1216,9 @@ static void assigned_dev_pci_write_config(PCIDevice *pci_dev, uint32_t address, + if (range_covers_byte(address, len, + pci_dev->msi_cap + PCI_MSI_FLAGS)) { + assigned_dev_update_msi(pci_dev); ++ } else if (ranges_overlap(address, len, /* 32bit MSI only */ ++ pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, 6)) { ++ assigned_dev_update_msi_msg(pci_dev); + } + } + if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) { +-- +1.7.1 + diff --git a/SOURCES/kvm-pci-assign-remove-the-duplicate-function-name-in-deb.patch b/SOURCES/kvm-pci-assign-remove-the-duplicate-function-name-in-deb.patch new file mode 100644 index 0000000..eee59d8 --- /dev/null +++ b/SOURCES/kvm-pci-assign-remove-the-duplicate-function-name-in-deb.patch @@ -0,0 +1,94 @@ +From ced48a3d562d22bdaaaf74d3238d69f4577f0fa8 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Fri, 1 Nov 2013 19:50:38 +0100 +Subject: [PATCH 03/25] pci-assign: remove the duplicate function name in debug message + +RH-Author: Alex Williamson +Message-id: <20131101195038.25461.59923.stgit@bling.home> +Patchwork-id: 55235 +O-Subject: [RHEL7 qemu-kvm PATCH 3/3] pci-assign: remove the duplicate function name in debug message +Bugzilla: 1025877 +RH-Acked-by: Bandan Das +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Orit Wasserman + +From: Wanlong Gao + +Bugzilla: 1025877 +Upstream commit: bd50cbaa0f34e47c5b82eba1cd1e88143018fa19 + +While DEBUG() already includes the function name. + +Signed-off-by: Wanlong Gao +Acked-by: Alex Williamson +Signed-off-by: Paolo Bonzini +--- + hw/i386/kvm/pci-assign.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/kvm/pci-assign.c | 12 ++++++------ + 1 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c +index a5885b4..7060605 100644 +--- a/hw/i386/kvm/pci-assign.c ++++ b/hw/i386/kvm/pci-assign.c +@@ -226,7 +226,7 @@ static uint32_t slow_bar_readb(void *opaque, hwaddr addr) + uint32_t r; + + r = *in; +- DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; + } +@@ -238,7 +238,7 @@ static uint32_t slow_bar_readw(void *opaque, hwaddr addr) + uint32_t r; + + r = *in; +- DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; + } +@@ -250,7 +250,7 @@ static uint32_t slow_bar_readl(void *opaque, hwaddr addr) + uint32_t r; + + r = *in; +- DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + + return r; + } +@@ -260,7 +260,7 @@ static void slow_bar_writeb(void *opaque, hwaddr addr, uint32_t val) + AssignedDevRegion *d = opaque; + uint8_t *out = d->u.r_virtbase + addr; + +- DEBUG("slow_bar_writeb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); + *out = val; + } + +@@ -269,7 +269,7 @@ static void slow_bar_writew(void *opaque, hwaddr addr, uint32_t val) + AssignedDevRegion *d = opaque; + uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr); + +- DEBUG("slow_bar_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); + *out = val; + } + +@@ -278,7 +278,7 @@ static void slow_bar_writel(void *opaque, hwaddr addr, uint32_t val) + AssignedDevRegion *d = opaque; + uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr); + +- DEBUG("slow_bar_writel addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); ++ DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); + *out = val; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-pci-host-Consistently-set-cannot_instantiate_with_de.patch b/SOURCES/kvm-pci-host-Consistently-set-cannot_instantiate_with_de.patch new file mode 100644 index 0000000..5c19908 --- /dev/null +++ b/SOURCES/kvm-pci-host-Consistently-set-cannot_instantiate_with_de.patch @@ -0,0 +1,385 @@ +From 8b91f65b26d0dd19fe47ba4ffea86081657fadf9 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:16 +0100 +Subject: [PATCH 40/81] pci-host: Consistently set cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-12-git-send-email-kwolf@redhat.com> +Patchwork-id: 55537 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 11/17] pci-host: Consistently set cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Many PCI host bridges consist of a sysbus device and a PCI device. +You need both for the thing to work. Arguably, these bridges should +be modelled as a single, composite devices instead of pairs of +seemingly independent devices you can only use together, but we're not +there, yet. + +Since the sysbus part can't be instantiated with device_add, yet, +permitting it with the PCI part is useless. We shouldn't offer +useless options to the user, so let's set +cannot_instantiate_with_device_add_yet for them. + +It's already set for Bonito, grackle, i440FX, and raven. Document +why. + +Set it for the others: dec-21154, e500-host-bridge, gt64120_pci, mch, +pbm-pci, ppc4xx-host-bridge, sh_pci_host, u3-agp, uni-north-agp, +uni-north-internal-pci, uni-north-pci, and versatile_pci_host. + +Signed-off-by: Markus Armbruster +Reviewed-by: Marcel Apfelbaum +(cherry picked from pending upstream submission) +Signed-off-by: Kevin Wolf +--- + hw/mips/gt64xxx_pci.c | 6 ++++++ + hw/pci-host/apb.c | 6 ++++++ + hw/pci-host/bonito.c | 6 +++++- + hw/pci-host/dec.c | 6 ++++++ + hw/pci-host/grackle.c | 6 +++++- + hw/pci-host/piix.c | 6 +++++- + hw/pci-host/ppce500.c | 5 +++++ + hw/pci-host/prep.c | 6 +++++- + hw/pci-host/q35.c | 5 +++++ + hw/pci-host/uninorth.c | 24 ++++++++++++++++++++++++ + hw/pci-host/versatile.c | 6 ++++++ + hw/ppc/ppc4xx_pci.c | 5 +++++ + hw/sh4/sh_pci.c | 6 ++++++ + 13 files changed, 89 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/mips/gt64xxx_pci.c | 6 ++++++ + hw/pci-host/apb.c | 6 ++++++ + hw/pci-host/bonito.c | 6 +++++- + hw/pci-host/dec.c | 6 ++++++ + hw/pci-host/grackle.c | 6 +++++- + hw/pci-host/piix.c | 6 +++++- + hw/pci-host/ppce500.c | 5 +++++ + hw/pci-host/prep.c | 6 +++++- + hw/pci-host/q35.c | 5 +++++ + hw/pci-host/uninorth.c | 24 ++++++++++++++++++++++++ + hw/pci-host/versatile.c | 6 ++++++ + hw/ppc/ppc4xx_pci.c | 5 +++++ + hw/sh4/sh_pci.c | 6 ++++++ + 13 files changed, 89 insertions(+), 4 deletions(-) + +diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c +index 189e865..3813495 100644 +--- a/hw/mips/gt64xxx_pci.c ++++ b/hw/mips/gt64xxx_pci.c +@@ -1150,12 +1150,18 @@ static int gt64120_pci_init(PCIDevice *d) + static void gt64120_pci_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = gt64120_pci_init; + k->vendor_id = PCI_VENDOR_ID_MARVELL; + k->device_id = PCI_DEVICE_ID_MARVELL_GT6412X; + k->revision = 0x10; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo gt64120_pci_info = { +diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c +index 5ac7556..a296dcf 100644 +--- a/hw/pci-host/apb.c ++++ b/hw/pci-host/apb.c +@@ -557,11 +557,17 @@ static int pbm_pci_host_init(PCIDevice *d) + static void pbm_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = pbm_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_SUN; + k->device_id = PCI_DEVICE_ID_SUN_SABRE; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo pbm_pci_host_info = { +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index c2a056a..021e652 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -811,8 +811,12 @@ static void bonito_class_init(ObjectClass *klass, void *data) + k->revision = 0x01; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "Host bridge"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_bonito; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo bonito_info = { +diff --git a/hw/pci-host/dec.c b/hw/pci-host/dec.c +index cff458b..aebb240 100644 +--- a/hw/pci-host/dec.c ++++ b/hw/pci-host/dec.c +@@ -116,6 +116,7 @@ static int dec_21154_pci_host_init(PCIDevice *d) + static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = dec_21154_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_DEC; +@@ -123,6 +124,11 @@ static void dec_21154_pci_host_class_init(ObjectClass *klass, void *data) + k->revision = 0x02; + k->class_id = PCI_CLASS_BRIDGE_PCI; + k->is_bridge = 1; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo dec_21154_pci_host_info = { +diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c +index 4643beb..315965d 100644 +--- a/hw/pci-host/grackle.c ++++ b/hw/pci-host/grackle.c +@@ -130,7 +130,11 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo grackle_pci_info = { +diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c +index 20cc682..56fc7be 100644 +--- a/hw/pci-host/piix.c ++++ b/hw/pci-host/piix.c +@@ -618,8 +618,12 @@ static void i440fx_class_init(ObjectClass *klass, void *data) + k->revision = 0x02; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "Host bridge"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_i440fx; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo i440fx_info = { +diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c +index 0d0a001..2dcd668 100644 +--- a/hw/pci-host/ppce500.c ++++ b/hw/pci-host/ppce500.c +@@ -387,6 +387,11 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_MPC8533E; + k->class_id = PCI_CLASS_PROCESSOR_POWERPC; + dc->desc = "Host bridge"; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo e500_host_bridge_info = { +diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c +index cdb401f..3e94d07 100644 +--- a/hw/pci-host/prep.c ++++ b/hw/pci-host/prep.c +@@ -196,7 +196,11 @@ static void raven_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "PReP Host Bridge - Motorola Raven"; + dc->vmsd = &vmstate_raven; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo raven_info = { +diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c +index 5f8e7ff..ed934c3 100644 +--- a/hw/pci-host/q35.c ++++ b/hw/pci-host/q35.c +@@ -295,6 +295,11 @@ static void mch_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_Q35_MCH; + k->revision = MCH_HOST_BRIDGE_REVISION_DEFUALT; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo mch_info = { +diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c +index fff235d..defdaa5 100644 +--- a/hw/pci-host/uninorth.c ++++ b/hw/pci-host/uninorth.c +@@ -351,12 +351,18 @@ static int unin_internal_pci_host_init(PCIDevice *d) + static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = unin_main_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_APPLE; + k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo unin_main_pci_host_info = { +@@ -369,12 +375,18 @@ static const TypeInfo unin_main_pci_host_info = { + static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = u3_agp_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_APPLE; + k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo u3_agp_pci_host_info = { +@@ -387,12 +399,18 @@ static const TypeInfo u3_agp_pci_host_info = { + static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = unin_agp_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_APPLE; + k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo unin_agp_pci_host_info = { +@@ -405,12 +423,18 @@ static const TypeInfo unin_agp_pci_host_info = { + static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = unin_internal_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_APPLE; + k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo unin_internal_pci_host_info = { +diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c +index 2f996d9..76d6cce 100644 +--- a/hw/pci-host/versatile.c ++++ b/hw/pci-host/versatile.c +@@ -467,11 +467,17 @@ static int versatile_pci_host_init(PCIDevice *d) + static void versatile_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = versatile_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_XILINX; + k->device_id = PCI_DEVICE_ID_XILINX_XC2VP30; + k->class_id = PCI_CLASS_PROCESSOR_CO; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo versatile_pci_host_info = { +diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c +index 599539b..ebe7efe 100644 +--- a/hw/ppc/ppc4xx_pci.c ++++ b/hw/ppc/ppc4xx_pci.c +@@ -380,6 +380,11 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) + k->vendor_id = PCI_VENDOR_ID_IBM; + k->device_id = PCI_DEVICE_ID_IBM_440GX; + k->class_id = PCI_CLASS_BRIDGE_OTHER; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo ppc4xx_host_bridge_info = { +diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c +index d213a90..f9c49c1 100644 +--- a/hw/sh4/sh_pci.c ++++ b/hw/sh4/sh_pci.c +@@ -150,10 +150,16 @@ static int sh_pci_host_init(PCIDevice *d) + static void sh_pci_host_class_init(ObjectClass *klass, void *data) + { + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); ++ DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = sh_pci_host_init; + k->vendor_id = PCI_VENDOR_ID_HITACHI; + k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R; ++ /* ++ * PCI-facing part of the host bridge, not usable without the ++ * host-facing part, which can't be device_add'ed, yet. ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo sh_pci_host_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-piix3-piix4-Clean-up-use-of-cannot_instantiate_with_.patch b/SOURCES/kvm-piix3-piix4-Clean-up-use-of-cannot_instantiate_with_.patch new file mode 100644 index 0000000..a15b048 --- /dev/null +++ b/SOURCES/kvm-piix3-piix4-Clean-up-use-of-cannot_instantiate_with_.patch @@ -0,0 +1,156 @@ +From 3a10d87d90ff5f2aeaf02addac57f5a3346f263c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:18 +0100 +Subject: [PATCH 42/81] piix3 piix4: Clean up use of cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-14-git-send-email-kwolf@redhat.com> +Patchwork-id: 55539 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 13/17] piix3 piix4: Clean up use of cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +A PIIX3/PIIX4 southbridge has multiple functions. We model each +function as a separate qdev. Two of them need some special wiring set +up in pc_init1() or mips_malta_init() to work: the ISA bridge at 01.0, +and the SMBus controller at 01.3. + +The IDE controller at 01.1 (piix3-ide, piix3-ide-xen, piix4-ide) has +always had cannot_instantiate_with_device_add_yet set, but there is no +obvious reason why device_add could not work for them. Drop it. +(cherry picked from pending upstream submission) + +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/acpi/piix4.c | 6 +++++- + hw/ide/piix.c | 3 --- + hw/isa/piix4.c | 6 +++++- + hw/pci-host/piix.c | 12 ++++++++++-- + 4 files changed, 20 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/acpi/piix4.c | 6 +++++- + hw/ide/piix.c | 3 --- + hw/isa/piix4.c | 6 +++++- + hw/pci-host/piix.c | 12 ++++++++++-- + 4 files changed, 20 insertions(+), 7 deletions(-) + +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index 46685b7..d79a7b0 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -494,9 +494,13 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) + k->revision = 0x03; + k->class_id = PCI_CLASS_BRIDGE_OTHER; + dc->desc = "PM"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_acpi; + dc->props = piix4_pm_properties; ++ /* ++ * Reason: part of PIIX4 southbridge, needs to be wired up, ++ * e.g. by mips_malta_init() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix4_pm_info = { +diff --git a/hw/ide/piix.c b/hw/ide/piix.c +index e6864b1..304cab0 100644 +--- a/hw/ide/piix.c ++++ b/hw/ide/piix.c +@@ -249,7 +249,6 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo piix3_ide_info = { +@@ -269,7 +268,6 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->unplug = pci_piix3_xen_ide_unplug; + } + +@@ -292,7 +290,6 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371AB; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo piix4_ide_info = { +diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c +index 10bf8ff..e7c75f1 100644 +--- a/hw/isa/piix4.c ++++ b/hw/isa/piix4.c +@@ -113,8 +113,12 @@ static void piix4_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; + k->class_id = PCI_CLASS_BRIDGE_ISA; + dc->desc = "ISA bridge"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_piix4; ++ /* ++ * Reason: part of PIIX4 southbridge, needs to be wired up, ++ * e.g. by mips_malta_init() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix4_info = { +diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c +index 56fc7be..c89b76b 100644 +--- a/hw/pci-host/piix.c ++++ b/hw/pci-host/piix.c +@@ -564,7 +564,6 @@ static void piix3_class_init(ObjectClass *klass, void *data) + + dc->desc = "ISA bridge"; + dc->vmsd = &vmstate_piix3; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->no_hotplug = 1; + k->init = piix3_initfn; + k->config_write = piix3_write_config; +@@ -572,6 +571,11 @@ static void piix3_class_init(ObjectClass *klass, void *data) + /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; + k->class_id = PCI_CLASS_BRIDGE_ISA; ++ /* ++ * Reason: part of PIIX3 southbridge, needs to be wired up by ++ * pc_piix.c's pc_init1() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix3_info = { +@@ -588,7 +592,6 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) + + dc->desc = "ISA bridge"; + dc->vmsd = &vmstate_piix3; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->no_hotplug = 1; + k->init = piix3_initfn; + k->config_write = piix3_write_config_xen; +@@ -596,6 +599,11 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) + /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_0; + k->class_id = PCI_CLASS_BRIDGE_ISA; ++ /* ++ * Reason: part of PIIX3 southbridge, needs to be wired up by ++ * pc_piix.c's pc_init1() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + }; + + static const TypeInfo piix3_xen_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-pvpanic-fix-fwcfg-for-big-endian-hosts.patch b/SOURCES/kvm-pvpanic-fix-fwcfg-for-big-endian-hosts.patch new file mode 100644 index 0000000..a8be1e3 --- /dev/null +++ b/SOURCES/kvm-pvpanic-fix-fwcfg-for-big-endian-hosts.patch @@ -0,0 +1,53 @@ +From c5760d0c0f29b8ae540b3ca553f461874447c32f Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:32 +0100 +Subject: [PATCH 73/81] pvpanic: fix fwcfg for big endian hosts + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-5-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55549 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 4/9] pvpanic: fix fwcfg for big endian hosts +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: "Michael S. Tsirkin" + +Convert port number to little endian when +exposing it in fw cfg. + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit fea7d5966a54a5e5400cd38897a95ea576b5af4d) +Signed-off-by: Marcel Apfelbaum +--- + hw/misc/pvpanic.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/pvpanic.c | 7 ++++--- + 1 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index 8263225..1aab787 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -99,10 +99,11 @@ static int pvpanic_isa_initfn(ISADevice *dev) + static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg) + { + PVPanicState *s = ISA_PVPANIC_DEVICE(dev); ++ uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port)); ++ *pvpanic_port = cpu_to_le16(s->ioport); + +- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", +- g_memdup(&s->ioport, sizeof(s->ioport)), +- sizeof(s->ioport)); ++ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, ++ sizeof(*pvpanic_port)); + } + + void pvpanic_init(ISABus *bus) +-- +1.7.1 + diff --git a/SOURCES/kvm-pvpanic-initialization-cleanup.patch b/SOURCES/kvm-pvpanic-initialization-cleanup.patch new file mode 100644 index 0000000..27b2394 --- /dev/null +++ b/SOURCES/kvm-pvpanic-initialization-cleanup.patch @@ -0,0 +1,115 @@ +From ed600bcecaa095b7cd0a6b5f52caaa3312fab840 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:31 +0100 +Subject: [PATCH 72/81] pvpanic: initialization cleanup + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-4-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55548 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 3/9] pvpanic: initialization cleanup +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: "Michael S. Tsirkin" + +Avoid use of static variables: PC systems +initialize pvpanic device through pvpanic_init, +so we can simply create the fw_cfg file at that point. +This also makes it possible to skip device +creation completely if fw_cfg is not there, e.g. for xen - +so the ports it reserves are not discoverable by guests. + +Also, make pvpanic_init void since callers ignore return +status anyway. + +Cc: Stefano Stabellini +Cc: Laszlo Ersek +Cc: Paul Durrant +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit bc3e6a0d6c8ab6cd7cd4b576ed567756f1dcabd2) +Signed-off-by: Marcel Apfelbaum + +Conflicts: + hw/misc/pvpanic.c + +Signed-off-by: Marcel Apfelbaum +--- + hw/misc/pvpanic.c | 32 +++++++++++++++++--------------- + include/hw/i386/pc.h | 2 +- + 2 files changed, 18 insertions(+), 16 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/pvpanic.c | 32 +++++++++++++++++--------------- + include/hw/i386/pc.h | 2 +- + 2 files changed, 18 insertions(+), 16 deletions(-) + +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index ddd8bdd..8263225 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -89,29 +89,31 @@ static const MemoryRegionOps pvpanic_ops = { + static int pvpanic_isa_initfn(ISADevice *dev) + { + PVPanicState *s = ISA_PVPANIC_DEVICE(dev); +- static bool port_configured; +- FWCfgState *fw_cfg; + + memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1); + isa_register_ioport(dev, &s->io, s->ioport); + +- if (!port_configured) { +- fw_cfg = fw_cfg_find(); +- if (fw_cfg) { +- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", +- g_memdup(&s->ioport, sizeof(s->ioport)), +- sizeof(s->ioport)); +- port_configured = true; +- } +- } +- + return 0; + } + +-int pvpanic_init(ISABus *bus) ++static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg) + { +- isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE); +- return 0; ++ PVPanicState *s = ISA_PVPANIC_DEVICE(dev); ++ ++ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", ++ g_memdup(&s->ioport, sizeof(s->ioport)), ++ sizeof(s->ioport)); ++} ++ ++void pvpanic_init(ISABus *bus) ++{ ++ ISADevice *dev; ++ FWCfgState *fw_cfg = fw_cfg_find(); ++ if (!fw_cfg) { ++ return; ++ } ++ dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE); ++ pvpanic_fw_cfg(dev, fw_cfg); + } + + static Property pvpanic_isa_properties[] = { +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 45487ba..72f6882 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -175,7 +175,7 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) + void pc_system_firmware_init(MemoryRegion *rom_memory); + + /* pvpanic.c */ +-int pvpanic_init(ISABus *bus); ++void pvpanic_init(ISABus *bus); + + /* e820 types */ + #define E820_RAM 1 +-- +1.7.1 + diff --git a/SOURCES/kvm-pvpanic-use-FWCfgState-explicitly.patch b/SOURCES/kvm-pvpanic-use-FWCfgState-explicitly.patch new file mode 100644 index 0000000..4d122e8 --- /dev/null +++ b/SOURCES/kvm-pvpanic-use-FWCfgState-explicitly.patch @@ -0,0 +1,47 @@ +From 7b4859ac57e46ec333b331f114afc65232bea76c Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:30 +0100 +Subject: [PATCH 71/81] pvpanic: use FWCfgState explicitly + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-3-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55547 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 2/9] pvpanic: use FWCfgState explicitly +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: "Michael S. Tsirkin" + +Use the type-safe FWCfgState structure instead +of the unsafe void *. + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit c3c4fe35be9f6c37388ba7615c6c33e8f4034438) +Signed-off-by: Marcel Apfelbaum +--- + hw/misc/pvpanic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/pvpanic.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index d17c3c9..ddd8bdd 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -90,7 +90,7 @@ static int pvpanic_isa_initfn(ISADevice *dev) + { + PVPanicState *s = ISA_PVPANIC_DEVICE(dev); + static bool port_configured; +- void *fw_cfg; ++ FWCfgState *fw_cfg; + + memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1); + isa_register_ioport(dev, &s->io, s->ioport); +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Add-ImageInfoSpecific-type.patch b/SOURCES/kvm-qapi-Add-ImageInfoSpecific-type.patch new file mode 100644 index 0000000..48ff22c --- /dev/null +++ b/SOURCES/kvm-qapi-Add-ImageInfoSpecific-type.patch @@ -0,0 +1,80 @@ +From d9c7fbe85bdeec60e97ba0c484dd9a88c0ba4994 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:34 +0100 +Subject: [PATCH 77/87] qapi: Add ImageInfoSpecific type + +RH-Author: Max Reitz +Message-id: <1383756824-6921-12-git-send-email-mreitz@redhat.com> +Patchwork-id: 55566 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 11/21] qapi: Add ImageInfoSpecific type +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +Add a new type ImageInfoSpecific as a union for image format specific +information in ImageInfo. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit f2bb8a8a47597634b74c161c44b9980c7f4e50ac) + +Signed-off-by: Max Reitz +--- + qapi-schema.json | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 18 +++++++++++++++++- + 1 files changed, 17 insertions(+), 1 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index 4091b99..934ac7f 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -210,6 +210,18 @@ + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } + + ## ++# @ImageInfoSpecific: ++# ++# A discriminated record of image format specific information structures. ++# ++# Since: 1.7 ++## ++ ++{ 'union': 'ImageInfoSpecific', ++ 'data': { ++ } } ++ ++## + # @ImageInfo: + # + # Information about a QEMU image file +@@ -238,6 +250,9 @@ + # + # @backing-image: #optional info of the backing image (since 1.6) + # ++# @format-specific: #optional structure supplying additional format-specific ++# information (since 1.7) ++# + # Since: 1.3 + # + ## +@@ -248,7 +263,8 @@ + '*cluster-size': 'int', '*encrypted': 'bool', + '*backing-filename': 'str', '*full-backing-filename': 'str', + '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], +- '*backing-image': 'ImageInfo' } } ++ '*backing-image': 'ImageInfo', ++ '*format-specific': 'ImageInfoSpecific' } } + + ## + # @ImageCheck: +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Add-consume-argument-to-qmp_input_get_object.patch b/SOURCES/kvm-qapi-Add-consume-argument-to-qmp_input_get_object.patch new file mode 100644 index 0000000..3827358 --- /dev/null +++ b/SOURCES/kvm-qapi-Add-consume-argument-to-qmp_input_get_object.patch @@ -0,0 +1,120 @@ +From adef92fecbb5d4e37e5e513954c088f9f1704418 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:13 +0200 +Subject: [PATCH 22/38] qapi: Add consume argument to qmp_input_get_object() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-23-git-send-email-kwolf@redhat.com> +Patchwork-id: 54209 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 22/32] qapi: Add consume argument to qmp_input_get_object() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This allows to just look at the next element without actually consuming +it. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit e8316d7e8e8339a9ea593ba821a0aad26908c0d5) + +Signed-off-by: Kevin Wolf +--- + qapi/qmp-input-visitor.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qapi/qmp-input-visitor.c | 19 ++++++++++--------- + 1 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c +index 59c5cac..70864a1 100644 +--- a/qapi/qmp-input-visitor.c ++++ b/qapi/qmp-input-visitor.c +@@ -41,13 +41,14 @@ static QmpInputVisitor *to_qiv(Visitor *v) + } + + static QObject *qmp_input_get_object(QmpInputVisitor *qiv, +- const char *name) ++ const char *name, ++ bool consume) + { + QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj; + + if (qobj) { + if (name && qobject_type(qobj) == QTYPE_QDICT) { +- if (qiv->stack[qiv->nb_stack - 1].h) { ++ if (qiv->stack[qiv->nb_stack - 1].h && consume) { + g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name); + } + return qdict_get(qobject_to_qdict(qobj), name); +@@ -117,7 +118,7 @@ static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind, + const char *name, size_t size, Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + Error *err = NULL; + + if (!qobj || qobject_type(qobj) != QTYPE_QDICT) { +@@ -159,7 +160,7 @@ static void qmp_input_end_implicit_struct(Visitor *v, Error **errp) + static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj || qobject_type(qobj) != QTYPE_QLIST) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", +@@ -211,7 +212,7 @@ static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, + Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj || qobject_type(qobj) != QTYPE_QINT) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", +@@ -226,7 +227,7 @@ static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name, + Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", +@@ -241,7 +242,7 @@ static void qmp_input_type_str(Visitor *v, char **obj, const char *name, + Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", +@@ -256,7 +257,7 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name, + Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT && + qobject_type(qobj) != QTYPE_QINT)) { +@@ -276,7 +277,7 @@ static void qmp_input_start_optional(Visitor *v, bool *present, + const char *name, Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +- QObject *qobj = qmp_input_get_object(qiv, name); ++ QObject *qobj = qmp_input_get_object(qiv, name, true); + + if (!qobj) { + *present = false; +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Add-optional-field-compressed-to-ImageInfo.patch b/SOURCES/kvm-qapi-Add-optional-field-compressed-to-ImageInfo.patch new file mode 100644 index 0000000..c8fe4f5 --- /dev/null +++ b/SOURCES/kvm-qapi-Add-optional-field-compressed-to-ImageInfo.patch @@ -0,0 +1,58 @@ +From db5a450f4c4b6f409573366eea87512ab3043dbe Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:42 +0100 +Subject: [PATCH 85/87] qapi: Add optional field 'compressed' to ImageInfo + +RH-Author: Max Reitz +Message-id: <1383756824-6921-20-git-send-email-mreitz@redhat.com> +Patchwork-id: 55574 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 19/21] qapi: Add optional field 'compressed' to ImageInfo +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit cbe82d7fb32e5d8e76434671d50853df5f50d560) + +Signed-off-by: Max Reitz +--- + qapi-schema.json | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index 3c00ddd..99b05b7 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -256,6 +256,8 @@ + # + # @encrypted: #optional true if the image is encrypted + # ++# @compressed: #optional true if the image is compressed (Since 1.7) ++# + # @backing-filename: #optional name of the backing file + # + # @full-backing-filename: #optional full path of the backing file +@@ -276,7 +278,7 @@ + { 'type': 'ImageInfo', + 'data': {'filename': 'str', 'format': 'str', '*dirty-flag': 'bool', + '*actual-size': 'int', 'virtual-size': 'int', +- '*cluster-size': 'int', '*encrypted': 'bool', ++ '*cluster-size': 'int', '*encrypted': 'bool', '*compressed': 'bool', + '*backing-filename': 'str', '*full-backing-filename': 'str', + '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], + '*backing-image': 'ImageInfo', +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Add-visitor-for-implicit-structs.patch b/SOURCES/kvm-qapi-Add-visitor-for-implicit-structs.patch new file mode 100644 index 0000000..5599aca --- /dev/null +++ b/SOURCES/kvm-qapi-Add-visitor-for-implicit-structs.patch @@ -0,0 +1,132 @@ +From a2a326f0a6b544335c49432248201fb811f1fc2b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:11 +0200 +Subject: [PATCH 20/38] qapi: Add visitor for implicit structs + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-21-git-send-email-kwolf@redhat.com> +Patchwork-id: 54207 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 20/32] qapi: Add visitor for implicit structs +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +These can be used when an embedded struct is parsed and members not +belonging to the struct may be present in the input (e.g. parsing a +flat namespace QMP union, where fields from both the base and one +of the alternative types are mixed in the JSON object) + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 761d524dbcc5bb41213dd0f238f43c273bc2b077) + +Signed-off-by: Kevin Wolf +--- + include/qapi/visitor-impl.h | 4 ++++ + include/qapi/visitor.h | 3 +++ + qapi/qapi-visit-core.c | 16 ++++++++++++++++ + qapi/qmp-input-visitor.c | 14 ++++++++++++++ + 4 files changed, 37 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + include/qapi/visitor-impl.h | 4 ++++ + include/qapi/visitor.h | 3 +++ + qapi/qapi-visit-core.c | 16 ++++++++++++++++ + qapi/qmp-input-visitor.c | 14 ++++++++++++++ + 4 files changed, 37 insertions(+), 0 deletions(-) + +diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h +index 5159964..5c1297f 100644 +--- a/include/qapi/visitor-impl.h ++++ b/include/qapi/visitor-impl.h +@@ -22,6 +22,10 @@ struct Visitor + const char *name, size_t size, Error **errp); + void (*end_struct)(Visitor *v, Error **errp); + ++ void (*start_implicit_struct)(Visitor *v, void **obj, size_t size, ++ Error **errp); ++ void (*end_implicit_struct)(Visitor *v, Error **errp); ++ + void (*start_list)(Visitor *v, const char *name, Error **errp); + GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp); + void (*end_list)(Visitor *v, Error **errp); +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index 1fef18c..a1cdd81 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -30,6 +30,9 @@ void visit_end_handle(Visitor *v, Error **errp); + void visit_start_struct(Visitor *v, void **obj, const char *kind, + const char *name, size_t size, Error **errp); + void visit_end_struct(Visitor *v, Error **errp); ++void visit_start_implicit_struct(Visitor *v, void **obj, size_t size, ++ Error **errp); ++void visit_end_implicit_struct(Visitor *v, Error **errp); + void visit_start_list(Visitor *v, const char *name, Error **errp); + GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp); + void visit_end_list(Visitor *v, Error **errp); +diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c +index 401ee6e..9b4d51b 100644 +--- a/qapi/qapi-visit-core.c ++++ b/qapi/qapi-visit-core.c +@@ -45,6 +45,22 @@ void visit_end_struct(Visitor *v, Error **errp) + v->end_struct(v, errp); + } + ++void visit_start_implicit_struct(Visitor *v, void **obj, size_t size, ++ Error **errp) ++{ ++ if (!error_is_set(errp) && v->start_implicit_struct) { ++ v->start_implicit_struct(v, obj, size, errp); ++ } ++} ++ ++void visit_end_implicit_struct(Visitor *v, Error **errp) ++{ ++ assert(!error_is_set(errp)); ++ if (v->end_implicit_struct) { ++ v->end_implicit_struct(v, errp); ++ } ++} ++ + void visit_start_list(Visitor *v, const char *name, Error **errp) + { + if (!error_is_set(errp)) { +diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c +index 67fb127..59c5cac 100644 +--- a/qapi/qmp-input-visitor.c ++++ b/qapi/qmp-input-visitor.c +@@ -144,6 +144,18 @@ static void qmp_input_end_struct(Visitor *v, Error **errp) + qmp_input_pop(qiv, errp); + } + ++static void qmp_input_start_implicit_struct(Visitor *v, void **obj, ++ size_t size, Error **errp) ++{ ++ if (obj) { ++ *obj = g_malloc0(size); ++ } ++} ++ ++static void qmp_input_end_implicit_struct(Visitor *v, Error **errp) ++{ ++} ++ + static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) + { + QmpInputVisitor *qiv = to_qiv(v); +@@ -293,6 +305,8 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) + + v->visitor.start_struct = qmp_input_start_struct; + v->visitor.end_struct = qmp_input_end_struct; ++ v->visitor.start_implicit_struct = qmp_input_start_implicit_struct; ++ v->visitor.end_implicit_struct = qmp_input_end_implicit_struct; + v->visitor.start_list = qmp_input_start_list; + v->visitor.next_list = qmp_input_next_list; + v->visitor.end_list = qmp_input_end_list; +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Anonymous-unions.patch b/SOURCES/kvm-qapi-Anonymous-unions.patch new file mode 100644 index 0000000..fc7c27c --- /dev/null +++ b/SOURCES/kvm-qapi-Anonymous-unions.patch @@ -0,0 +1,379 @@ +From fafd52c6d2c32e24ae83b4d534c6e2f72f53795d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:16 +0200 +Subject: [PATCH 25/38] qapi: Anonymous unions + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-26-git-send-email-kwolf@redhat.com> +Patchwork-id: 54212 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 25/32] qapi: Anonymous unions +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +The discriminator for anonymous unions is the data type. This allows to +have a union type that allows both of these: + + { 'file': 'my_existing_block_device_id' } + { 'file': { 'filename': '/tmp/mydisk.qcow2', 'read-only': true } } + +Unions like this are specified in the schema with an empty dict as +discriminator. For this example you could take: + + { 'union': 'BlockRef', + 'discriminator': {}, + 'data': { 'definition': 'BlockOptions', + 'reference': 'str' } } + { 'type': 'ExampleObject', + 'data: { 'file': 'BlockRef' } } + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 69dd62dfd60631ba69201d8a197fde1ece4b4df3) + +Signed-off-by: Kevin Wolf +--- + docs/qapi-code-gen.txt | 25 ++++++++++++++++++++++++ + include/qapi/qmp/qobject.h | 1 + + include/qapi/visitor-impl.h | 2 ++ + include/qapi/visitor.h | 3 +++ + qapi/qapi-visit-core.c | 9 +++++++++ + qapi/qmp-input-visitor.c | 14 ++++++++++++++ + qobject/qjson.c | 2 ++ + scripts/qapi-types.py | 42 ++++++++++++++++++++++++++++++++++++++++ + scripts/qapi-visit.py | 47 +++++++++++++++++++++++++++++++++++++++++++++ + scripts/qapi.py | 15 +++++++++++++++ + 10 files changed, 160 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + docs/qapi-code-gen.txt | 25 ++++++++++++++++++++++ + include/qapi/qmp/qobject.h | 1 + + include/qapi/visitor-impl.h | 2 + + include/qapi/visitor.h | 3 ++ + qapi/qapi-visit-core.c | 9 ++++++++ + qapi/qmp-input-visitor.c | 14 ++++++++++++ + qobject/qjson.c | 2 + + scripts/qapi-types.py | 42 ++++++++++++++++++++++++++++++++++++++ + scripts/qapi-visit.py | 47 +++++++++++++++++++++++++++++++++++++++++++ + scripts/qapi.py | 15 +++++++++++++ + 10 files changed, 160 insertions(+), 0 deletions(-) + +diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt +index 11f19cf..0ce045c 100644 +--- a/docs/qapi-code-gen.txt ++++ b/docs/qapi-code-gen.txt +@@ -125,6 +125,31 @@ Resulting in this JSON object: + "lazy-refcounts": true } + + ++A special type of unions are anonymous unions. They don't form a dictionary in ++the wire format but allow the direct use of different types in their place. As ++they aren't structured, they don't have any explicit discriminator but use ++the (QObject) data type of their value as an implicit discriminator. This means ++that they are restricted to using only one discriminator value per QObject ++type. For example, you cannot have two different complex types in an anonymous ++union, or two different integer types. ++ ++Anonymous unions are declared using an empty dictionary as their discriminator. ++The discriminator values never appear on the wire, they are only used in the ++generated C code. Anonymous unions cannot have a base type. ++ ++ { 'union': 'BlockRef', ++ 'discriminator': {}, ++ 'data': { 'definition': 'BlockdevOptions', ++ 'reference': 'str' } } ++ ++This example allows using both of the following example objects: ++ ++ { "file": "my_existing_block_device_id" } ++ { "file": { "driver": "file", ++ "readonly": false, ++ 'filename': "/tmp/mydisk.qcow2" } } ++ ++ + === Commands === + + Commands are defined by using a list containing three members. The first +diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h +index 9124649..d0bbc7c 100644 +--- a/include/qapi/qmp/qobject.h ++++ b/include/qapi/qmp/qobject.h +@@ -44,6 +44,7 @@ typedef enum { + QTYPE_QFLOAT, + QTYPE_QBOOL, + QTYPE_QERROR, ++ QTYPE_MAX, + } qtype_code; + + struct QObject; +diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h +index 5c1297f..f3fa420 100644 +--- a/include/qapi/visitor-impl.h ++++ b/include/qapi/visitor-impl.h +@@ -32,6 +32,8 @@ struct Visitor + + void (*type_enum)(Visitor *v, int *obj, const char *strings[], + const char *kind, const char *name, Error **errp); ++ void (*get_next_type)(Visitor *v, int *kind, const int *qobjects, ++ const char *name, Error **errp); + + void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp); + void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp); +diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h +index a1cdd81..aa9e771 100644 +--- a/include/qapi/visitor.h ++++ b/include/qapi/visitor.h +@@ -13,6 +13,7 @@ + #ifndef QAPI_VISITOR_CORE_H + #define QAPI_VISITOR_CORE_H + ++#include "qapi/qmp/qobject.h" + #include "qapi/error.h" + #include + +@@ -39,6 +40,8 @@ void visit_end_list(Visitor *v, Error **errp); + void visit_start_optional(Visitor *v, bool *present, const char *name, + Error **errp); + void visit_end_optional(Visitor *v, Error **errp); ++void visit_get_next_type(Visitor *v, int *obj, const int *qtypes, ++ const char *name, Error **errp); + void visit_type_enum(Visitor *v, int *obj, const char *strings[], + const char *kind, const char *name, Error **errp); + void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp); +diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c +index 9b4d51b..d6a4012 100644 +--- a/qapi/qapi-visit-core.c ++++ b/qapi/qapi-visit-core.c +@@ -12,6 +12,7 @@ + */ + + #include "qemu-common.h" ++#include "qapi/qmp/qobject.h" + #include "qapi/qmp/qerror.h" + #include "qapi/visitor.h" + #include "qapi/visitor-impl.h" +@@ -98,6 +99,14 @@ void visit_end_optional(Visitor *v, Error **errp) + } + } + ++void visit_get_next_type(Visitor *v, int *obj, const int *qtypes, ++ const char *name, Error **errp) ++{ ++ if (!error_is_set(errp) && v->get_next_type) { ++ v->get_next_type(v, obj, qtypes, name, errp); ++ } ++} ++ + void visit_type_enum(Visitor *v, int *obj, const char *strings[], + const char *kind, const char *name, Error **errp) + { +diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c +index 70864a1..bf42c04 100644 +--- a/qapi/qmp-input-visitor.c ++++ b/qapi/qmp-input-visitor.c +@@ -208,6 +208,19 @@ static void qmp_input_end_list(Visitor *v, Error **errp) + qmp_input_pop(qiv, errp); + } + ++static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects, ++ const char *name, Error **errp) ++{ ++ QmpInputVisitor *qiv = to_qiv(v); ++ QObject *qobj = qmp_input_get_object(qiv, name, false); ++ ++ if (!qobj) { ++ error_set(errp, QERR_MISSING_PARAMETER, name ? name : "null"); ++ return; ++ } ++ *kind = qobjects[qobject_type(qobj)]; ++} ++ + static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, + Error **errp) + { +@@ -317,6 +330,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) + v->visitor.type_str = qmp_input_type_str; + v->visitor.type_number = qmp_input_type_number; + v->visitor.start_optional = qmp_input_start_optional; ++ v->visitor.get_next_type = qmp_input_get_next_type; + + qmp_input_push(v, obj, NULL); + qobject_incref(obj); +diff --git a/qobject/qjson.c b/qobject/qjson.c +index 19085a1..6cf2511 100644 +--- a/qobject/qjson.c ++++ b/qobject/qjson.c +@@ -260,6 +260,8 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) + /* XXX: should QError be emitted? */ + case QTYPE_NONE: + break; ++ case QTYPE_MAX: ++ abort(); + } + } + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index 3d9af3c..20f4bdf 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -144,6 +144,40 @@ typedef enum %(name)s + + return lookup_decl + enum_decl + ++def generate_anon_union_qtypes(expr): ++ ++ name = expr['union'] ++ members = expr['data'] ++ ++ ret = mcgen(''' ++const int %(name)s_qtypes[QTYPE_MAX] = { ++''', ++ name=name) ++ ++ for key in members: ++ qapi_type = members[key] ++ if builtin_type_qtypes.has_key(qapi_type): ++ qtype = builtin_type_qtypes[qapi_type] ++ elif find_struct(qapi_type): ++ qtype = "QTYPE_QDICT" ++ elif find_union(qapi_type): ++ qtype = "QTYPE_QDICT" ++ else: ++ assert False, "Invalid anonymous union member" ++ ++ ret += mcgen(''' ++ [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s, ++''', ++ qtype = qtype, ++ abbrev = de_camel_case(name).upper(), ++ enum = c_fun(de_camel_case(key),False).upper()) ++ ++ ret += mcgen(''' ++}; ++''') ++ return ret ++ ++ + def generate_union(expr): + + name = expr['union'] +@@ -184,6 +218,12 @@ struct %(name)s + ret += mcgen(''' + }; + ''') ++ if discriminator == {}: ++ ret += mcgen(''' ++extern const int %(name)s_qtypes[]; ++''', ++ name=name) ++ + + return ret + +@@ -336,6 +376,8 @@ for expr in exprs: + ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" + ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) + fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) ++ if expr.get('discriminator') == {}: ++ fdef.write(generate_anon_union_qtypes(expr)) + else: + continue + fdecl.write(ret) +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index b1c1ad6..367cf7a 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -176,6 +176,49 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e + ''', + name=name) + ++def generate_visit_anon_union(name, members): ++ ret = mcgen(''' ++ ++void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) ++{ ++ Error *err = NULL; ++ ++ if (!error_is_set(errp)) { ++ visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err); ++ visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err); ++ switch ((*obj)->kind) { ++''', ++ name=name) ++ ++ for key in members: ++ assert (members[key] in builtin_types ++ or find_struct(members[key]) ++ or find_union(members[key])), "Invalid anonymous union member" ++ ++ ret += mcgen(''' ++ case %(abbrev)s_KIND_%(enum)s: ++ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); ++ break; ++''', ++ abbrev = de_camel_case(name).upper(), ++ enum = c_fun(de_camel_case(key),False).upper(), ++ c_type = type_name(members[key]), ++ c_name = c_fun(key)) ++ ++ ret += mcgen(''' ++ default: ++ abort(); ++ } ++ error_propagate(errp, err); ++ err = NULL; ++ visit_end_implicit_struct(m, &err); ++ } ++} ++''') ++ ++ return ret ++ ++ + def generate_visit_union(expr): + + name = expr['union'] +@@ -184,6 +227,10 @@ def generate_visit_union(expr): + base = expr.get('base') + discriminator = expr.get('discriminator') + ++ if discriminator == {}: ++ assert not base ++ return generate_visit_anon_union(name, members) ++ + ret = generate_visit_enum('%sKind' % name, members.keys()) + + if base: +diff --git a/scripts/qapi.py b/scripts/qapi.py +index 3a54c7f..38c808e 100644 +--- a/scripts/qapi.py ++++ b/scripts/qapi.py +@@ -17,6 +17,21 @@ builtin_types = [ + 'uint8', 'uint16', 'uint32', 'uint64' + ] + ++builtin_type_qtypes = { ++ 'str': 'QTYPE_QSTRING', ++ 'int': 'QTYPE_QINT', ++ 'number': 'QTYPE_QFLOAT', ++ 'bool': 'QTYPE_QBOOL', ++ 'int8': 'QTYPE_QINT', ++ 'int16': 'QTYPE_QINT', ++ 'int32': 'QTYPE_QINT', ++ 'int64': 'QTYPE_QINT', ++ 'uint8': 'QTYPE_QINT', ++ 'uint16': 'QTYPE_QINT', ++ 'uint32': 'QTYPE_QINT', ++ 'uint64': 'QTYPE_QINT', ++} ++ + def tokenize(data): + while len(data): + ch = data[0] +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-Flat-unions-with-arbitrary-discriminator.patch b/SOURCES/kvm-qapi-Flat-unions-with-arbitrary-discriminator.patch new file mode 100644 index 0000000..6efb8f0 --- /dev/null +++ b/SOURCES/kvm-qapi-Flat-unions-with-arbitrary-discriminator.patch @@ -0,0 +1,284 @@ +From e25370368e98e6d8766e50b7f13e3543e1c3ef9b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:12 +0200 +Subject: [PATCH 21/38] qapi: Flat unions with arbitrary discriminator + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-22-git-send-email-kwolf@redhat.com> +Patchwork-id: 54208 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 21/32] qapi: Flat unions with arbitrary discriminator +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Instead of the rather verbose syntax that distinguishes base and +subclass fields... + + { "type": "file", + "read-only": true, + "data": { + "filename": "test" + } } + +...we can now have both in the same namespace, allowing a more direct +mapping of the command line, and moving fields between the common base +and subclasses without breaking the API: + + { "driver": "file", + "read-only": true, + "filename": "test" } + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 50f2bdc75c5ee00617ad874c9ceac2cea660aa1e) + +Signed-off-by: Kevin Wolf +--- + docs/qapi-code-gen.txt | 22 ++++++++++++ + scripts/qapi-types.py | 11 ++++-- + scripts/qapi-visit.py | 90 +++++++++++++++++++++++++++++++++++++------------- + 3 files changed, 98 insertions(+), 25 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + docs/qapi-code-gen.txt | 22 ++++++++++++ + scripts/qapi-types.py | 11 +++++- + scripts/qapi-visit.py | 90 +++++++++++++++++++++++++++++++++++------------ + 3 files changed, 98 insertions(+), 25 deletions(-) + +diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt +index f6f8d33..11f19cf 100644 +--- a/docs/qapi-code-gen.txt ++++ b/docs/qapi-code-gen.txt +@@ -103,6 +103,28 @@ And it looks like this on the wire: + "data" : { "backing-file": "/some/place/my-image", + "lazy-refcounts": true } } + ++ ++Flat union types avoid the nesting on the wire. They are used whenever a ++specific field of the base type is declared as the discriminator ('type' is ++then no longer generated). The discriminator must always be a string field. ++The above example can then be modified as follows: ++ ++ { 'type': 'BlockdevCommonOptions', ++ 'data': { 'driver': 'str', 'readonly': 'bool' } } ++ { 'union': 'BlockdevOptions', ++ 'base': 'BlockdevCommonOptions', ++ 'discriminator': 'driver', ++ 'data': { 'raw': 'RawOptions', ++ 'qcow2': 'Qcow2Options' } } ++ ++Resulting in this JSON object: ++ ++ { "driver": "qcow2", ++ "readonly": false, ++ "backing-file": "/some/place/my-image", ++ "lazy-refcounts": true } ++ ++ + === Commands === + + Commands are defined by using a list containing three members. The first +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index c0684a7..f139bfe 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -135,7 +135,9 @@ def generate_union(expr): + + name = expr['union'] + typeinfo = expr['data'] ++ + base = expr.get('base') ++ discriminator = expr.get('discriminator') + + ret = mcgen(''' + struct %(name)s +@@ -158,8 +160,13 @@ struct %(name)s + ''') + + if base: +- struct = find_struct(base) +- ret += generate_struct_fields(struct['data']) ++ base_fields = find_struct(base)['data'] ++ if discriminator: ++ base_fields = base_fields.copy() ++ del base_fields[discriminator] ++ ret += generate_struct_fields(base_fields) ++ else: ++ assert not discriminator + + ret += mcgen(''' + }; +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index be56ba4..b1c1ad6 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -17,8 +17,30 @@ import os + import getopt + import errno + +-def generate_visit_struct_fields(field_prefix, members): ++def generate_visit_struct_fields(name, field_prefix, fn_prefix, members): ++ substructs = [] + ret = '' ++ full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix) ++ ++ for argname, argentry, optional, structured in parse_args(members): ++ if structured: ++ if not fn_prefix: ++ nested_fn_prefix = argname ++ else: ++ nested_fn_prefix = "%s_%s" % (fn_prefix, argname) ++ ++ nested_field_prefix = "%s%s." % (field_prefix, argname) ++ ret += generate_visit_struct_fields(name, nested_field_prefix, ++ nested_fn_prefix, argentry) ++ ++ ret += mcgen(''' ++ ++static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error **errp) ++{ ++ Error *err = NULL; ++''', ++ name=name, full_name=full_name) ++ push_indent() + + for argname, argentry, optional, structured in parse_args(members): + if optional: +@@ -31,7 +53,7 @@ if (obj && (*obj)->%(prefix)shas_%(c_name)s) { + push_indent() + + if structured: +- ret += generate_visit_struct_body(field_prefix + argname, argname, argentry) ++ ret += generate_visit_struct_body(full_name, argname, argentry) + else: + ret += mcgen(''' + visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); +@@ -47,6 +69,12 @@ visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", + visit_end_optional(m, &err); + ''') + ++ pop_indent() ++ ret += mcgen(''' ++ ++ error_propagate(errp, err); ++} ++''') + return ret + + +@@ -56,8 +84,9 @@ if (!error_is_set(errp)) { + ''') + push_indent() + ++ full_name = name if not field_prefix else "%s_%s" % (field_prefix, name) ++ + if len(field_prefix): +- field_prefix = field_prefix + "." + ret += mcgen(''' + Error **errp = &err; /* from outer scope */ + Error *err = NULL; +@@ -74,20 +103,14 @@ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); + ret += mcgen(''' + if (!err) { + if (!obj || *obj) { +-''') +- push_indent() +- push_indent() +- +- ret += generate_visit_struct_fields(field_prefix, members) +- pop_indent() +- ret += mcgen(''' +- error_propagate(errp, err); +- err = NULL; +-} +-''') ++ visit_type_%(name)s_fields(m, obj, &err); ++ error_propagate(errp, err); ++ err = NULL; ++ } ++''', ++ name=full_name) + + pop_indent() +- pop_indent() + ret += mcgen(''' + /* Always call end_struct if start_struct succeeded. */ + visit_end_struct(m, &err); +@@ -98,7 +121,9 @@ if (!err) { + return ret + + def generate_visit_struct(name, members): +- ret = mcgen(''' ++ ret = generate_visit_struct_fields(name, "", "", members) ++ ++ ret += mcgen(''' + + void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) + { +@@ -157,9 +182,17 @@ def generate_visit_union(expr): + members = expr['data'] + + base = expr.get('base') ++ discriminator = expr.get('discriminator') + + ret = generate_visit_enum('%sKind' % name, members.keys()) + ++ if base: ++ base_fields = find_struct(base)['data'] ++ if discriminator: ++ base_fields = base_fields.copy() ++ del base_fields[discriminator] ++ ret += generate_visit_struct_fields(name, "", "", base_fields) ++ + ret += mcgen(''' + + void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) +@@ -179,23 +212,34 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** + push_indent() + + if base: +- struct = find_struct(base) +- push_indent() +- ret += generate_visit_struct_fields("", struct['data']) +- pop_indent() ++ ret += mcgen(''' ++ visit_type_%(name)s_fields(m, obj, &err); ++''', ++ name=name) + + pop_indent() + ret += mcgen(''' +- visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); ++ visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err); + if (!err) { + switch ((*obj)->kind) { + ''', +- name=name) ++ name=name, type="type" if not discriminator else discriminator) + + for key in members: ++ if not discriminator: ++ fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);' ++ else: ++ fmt = '''visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(c_type)s), &err); ++ if (!err) { ++ visit_type_%(c_type)s_fields(m, &(*obj)->%(c_name)s, &err); ++ error_propagate(errp, err); ++ err = NULL; ++ visit_end_implicit_struct(m, &err); ++ }''' ++ + ret += mcgen(''' + case %(abbrev)s_KIND_%(enum)s: +- visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err); ++ ''' + fmt + ''' + break; + ''', + abbrev = de_camel_case(name).upper(), +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-enable-generation-of-native-list-code.patch b/SOURCES/kvm-qapi-enable-generation-of-native-list-code.patch new file mode 100644 index 0000000..b0d2256 --- /dev/null +++ b/SOURCES/kvm-qapi-enable-generation-of-native-list-code.patch @@ -0,0 +1,74 @@ +From f346ff306b647fe1db3ffe8c9880178382c7b98d Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Fri, 8 Nov 2013 06:13:58 +0100 +Subject: [PATCH 3/4] qapi: enable generation of native list code + +RH-Author: Amos Kong +Message-id: <1383891239-29531-4-git-send-email-akong@redhat.com> +Patchwork-id: 55610 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 3/4] qapi: enable generation of native list code +Bugzilla: 848203 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +From: Michael Roth + +Also, fix a dependency issue with libqemuutil: qemu-sockets.c needs +qapi-types.c/qapi-visit.c + +Signed-off-by: Michael Roth +Reviewed-by: Laszlo Ersek +Reviewed-by: Amos Kong +Signed-off-by: Luiz Capitulino +(cherry picked from commit 0b400e792718f59275d5d54c21de9a589b35a81f) +--- + Makefile | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + Makefile | 10 +++++----- + 1 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/Makefile b/Makefile +index 45048a3..66774de 100644 +--- a/Makefile ++++ b/Makefile +@@ -183,7 +183,7 @@ Makefile: $(version-obj-y) $(version-lobj-y) + # Build libraries + + libqemustub.a: $(stub-obj-y) +-libqemuutil.a: $(util-obj-y) ++libqemuutil.a: $(util-obj-y) qapi-types.o qapi-visit.o + + ###################################################################### + +@@ -239,20 +239,20 @@ $(SRC_PATH)/qapi-schema-rhel.json: $(SRC_PATH)/qapi-schema.json + ifeq ($(CONFIG_LIVE_BLOCK_OPS),y) + qapi-types.c qapi-types.h :\ + $(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) +- $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -b < $<, " GEN $@") + qapi-visit.c qapi-visit.h :\ + $(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) +- $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@") + qmp-commands.h qmp-marshal.c :\ + $(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") + else + qapi-types.c qapi-types.h :\ + $(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) +- $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, " GEN $@") ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." -b < $<, " GEN $@") + qapi-visit.c qapi-visit.h :\ + $(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) +- $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." < $<, " GEN $@") ++ $(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "." -b < $<, " GEN $@") + qmp-commands.h qmp-marshal.c :\ + $(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) + $(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-qapi-types.py-native-list-support.patch b/SOURCES/kvm-qapi-qapi-types.py-native-list-support.patch new file mode 100644 index 0000000..c5fe402 --- /dev/null +++ b/SOURCES/kvm-qapi-qapi-types.py-native-list-support.patch @@ -0,0 +1,179 @@ +From f45283cb91d07fd280fcf503a486effc1a96fa5e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:15 +0200 +Subject: [PATCH 24/38] qapi: qapi-types.py, native list support + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-25-git-send-email-kwolf@redhat.com> +Patchwork-id: 54211 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 24/32] qapi: qapi-types.py, native list support +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +From: Michael Roth + +Bugzilla: 1005818 + +Teach type generators about native types so they can generate the +appropriate linked list types. + +Signed-off-by: Michael Roth +Reviewed-by: Laszlo Ersek +Reviewed-by: Amos Kong +Signed-off-by: Luiz Capitulino +(cherry picked from commit c0afa9c5f717d0ebf10c70c305974ebbffe4c71f) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-types.py | 45 ++++++++++++++++++++++++++++++++++++++++++--- + scripts/qapi.py | 23 +++++++++++++++++++++++ + 2 files changed, 65 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-types.py | 45 ++++++++++++++++++++++++++++++++++++++++++--- + scripts/qapi.py | 23 +++++++++++++++++++++++ + 2 files changed, 65 insertions(+), 3 deletions(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index f139bfe..3d9af3c 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -16,8 +16,21 @@ import os + import getopt + import errno + +-def generate_fwd_struct(name, members): ++def generate_fwd_struct(name, members, builtin_type=False): ++ if builtin_type: ++ return mcgen(''' ++ ++typedef struct %(name)sList ++{ ++ %(type)s value; ++ struct %(name)sList *next; ++} %(name)sList; ++''', ++ type=c_type(name), ++ name=name) ++ + return mcgen(''' ++ + typedef struct %(name)s %(name)s; + + typedef struct %(name)sList +@@ -183,6 +196,7 @@ void qapi_free_%(type)s(%(c_type)s obj); + + def generate_type_cleanup(name): + ret = mcgen(''' ++ + void qapi_free_%(type)s(%(c_type)s obj) + { + QapiDeallocVisitor *md; +@@ -203,8 +217,9 @@ void qapi_free_%(type)s(%(c_type)s obj) + + + try: +- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", +- ["source", "header", "prefix=", "output-dir="]) ++ opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", ++ ["source", "header", "builtins", ++ "prefix=", "output-dir="]) + except getopt.GetoptError, err: + print str(err) + sys.exit(1) +@@ -216,6 +231,7 @@ h_file = 'qapi-types.h' + + do_c = False + do_h = False ++do_builtins = False + + for o, a in opts: + if o in ("-p", "--prefix"): +@@ -226,6 +242,8 @@ for o, a in opts: + do_c = True + elif o in ("-h", "--header"): + do_h = True ++ elif o in ("-b", "--builtins"): ++ do_builtins = True + + if not do_c and not do_h: + do_c = True +@@ -301,6 +319,11 @@ fdecl.write(mcgen(''' + exprs = parse_schema(sys.stdin) + exprs = filter(lambda expr: not expr.has_key('gen'), exprs) + ++fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL")) ++for typename in builtin_types: ++ fdecl.write(generate_fwd_struct(typename, None, builtin_type=True)) ++fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL")) ++ + for expr in exprs: + ret = "\n" + if expr.has_key('type'): +@@ -317,6 +340,22 @@ for expr in exprs: + continue + fdecl.write(ret) + ++# to avoid header dependency hell, we always generate declarations ++# for built-in types in our header files and simply guard them ++fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) ++for typename in builtin_types: ++ fdecl.write(generate_type_cleanup_decl(typename + "List")) ++fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) ++ ++# ...this doesn't work for cases where we link in multiple objects that ++# have the functions defined, so we use -b option to provide control ++# over these cases ++if do_builtins: ++ fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) ++ for typename in builtin_types: ++ fdef.write(generate_type_cleanup(typename + "List")) ++ fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) ++ + for expr in exprs: + ret = "\n" + if expr.has_key('type'): +diff --git a/scripts/qapi.py b/scripts/qapi.py +index 03c42a9..3a54c7f 100644 +--- a/scripts/qapi.py ++++ b/scripts/qapi.py +@@ -11,6 +11,12 @@ + + from ordereddict import OrderedDict + ++builtin_types = [ ++ 'str', 'int', 'number', 'bool', ++ 'int8', 'int16', 'int32', 'int64', ++ 'uint8', 'uint16', 'uint32', 'uint64' ++] ++ + def tokenize(data): + while len(data): + ch = data[0] +@@ -274,3 +280,20 @@ def guardname(filename): + for substr in [".", " ", "-"]: + guard = guard.replace(substr, "_") + return guard.upper() + '_H' ++ ++def guardstart(name): ++ return mcgen(''' ++ ++#ifndef %(name)s ++#define %(name)s ++ ++''', ++ name=guardname(name)) ++ ++def guardend(name): ++ return mcgen(''' ++ ++#endif /* %(name)s */ ++ ++''', ++ name=guardname(name)) +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-qapi-visit.py-fix-list-handling-for-union-types.patch b/SOURCES/kvm-qapi-qapi-visit.py-fix-list-handling-for-union-types.patch new file mode 100644 index 0000000..eff4f9b --- /dev/null +++ b/SOURCES/kvm-qapi-qapi-visit.py-fix-list-handling-for-union-types.patch @@ -0,0 +1,53 @@ +From 3d016c34cdcc3cada9303eaa0a57ce847367e5d8 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Fri, 8 Nov 2013 06:13:56 +0100 +Subject: [PATCH 1/4] qapi: qapi-visit.py, fix list handling for union types + +RH-Author: Amos Kong +Message-id: <1383891239-29531-2-git-send-email-akong@redhat.com> +Patchwork-id: 55608 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 1/4] qapi: qapi-visit.py, fix list handling for union types +Bugzilla: 848203 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +From: Michael Roth + +Currently we assume non-list types when generating visitor routines for +union types. This is broken, since values like ['Type'] need to mapped +to 'TypeList'. + +We already have a type_name() function to handle this that we use for +generating struct visitors, so use that here as well. + +Signed-off-by: Michael Roth +Reviewed-by: Laszlo Ersek +Reviewed-by: Amos Kong +Signed-off-by: Luiz Capitulino +(cherry picked from commit c664aef551714e91b7d83a28617b6e767db30d11) +--- + scripts/qapi-visit.py | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-visit.py | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index 71004ae..fc2b67a 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -309,7 +309,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** + ''', + abbrev = de_camel_case(name).upper(), + enum = c_fun(de_camel_case(key),False).upper(), +- c_type=members[key], ++ c_type=type_name(members[key]), + c_name=c_fun(key)) + + ret += mcgen(''' +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-qapi-visit.py-native-list-support.patch b/SOURCES/kvm-qapi-qapi-visit.py-native-list-support.patch new file mode 100644 index 0000000..0387452 --- /dev/null +++ b/SOURCES/kvm-qapi-qapi-visit.py-native-list-support.patch @@ -0,0 +1,117 @@ +From 19832bf960bb31814a0d950b01fff45e2618be27 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Fri, 8 Nov 2013 06:13:57 +0100 +Subject: [PATCH 2/4] qapi: qapi-visit.py, native list support + +RH-Author: Amos Kong +Message-id: <1383891239-29531-3-git-send-email-akong@redhat.com> +Patchwork-id: 55609 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 2/4] qapi: qapi-visit.py, native list support +Bugzilla: 848203 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +From: Michael Roth + +Teach visitor generators about native types so they can generate the +appropriate visitor routines. + +Signed-off-by: Michael Roth +Reviewed-by: Laszlo Ersek +Reviewed-by: Amos Kong +Signed-off-by: Luiz Capitulino +(cherry picked from commit 7c946bc418db6b2a11f89b3465424fef48f714eb) +--- + scripts/qapi-visit.py | 34 +++++++++++++++++++++++++++++----- + 1 files changed, 29 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-visit.py | 34 +++++++++++++++++++++++++++++----- + 1 files changed, 29 insertions(+), 5 deletions(-) + +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index fc2b67a..c39e628 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -337,12 +337,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** + + return ret + +-def generate_declaration(name, members, genlist=True): +- ret = mcgen(''' ++def generate_declaration(name, members, genlist=True, builtin_type=False): ++ ret = "" ++ if not builtin_type: ++ ret += mcgen(''' + + void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp); + ''', +- name=name) ++ name=name) + + if genlist: + ret += mcgen(''' +@@ -370,8 +372,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e + name=name) + + try: +- opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", +- ["source", "header", "prefix=", "output-dir="]) ++ opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", ++ ["source", "header", "builtins", "prefix=", ++ "output-dir="]) + except getopt.GetoptError, err: + print str(err) + sys.exit(1) +@@ -383,6 +386,7 @@ h_file = 'qapi-visit.h' + + do_c = False + do_h = False ++do_builtins = False + + for o, a in opts: + if o in ("-p", "--prefix"): +@@ -393,6 +397,8 @@ for o, a in opts: + do_c = True + elif o in ("-h", "--header"): + do_h = True ++ elif o in ("-b", "--builtins"): ++ do_builtins = True + + if not do_c and not do_h: + do_c = True +@@ -459,11 +465,29 @@ fdecl.write(mcgen(''' + + #include "qapi/visitor.h" + #include "%(prefix)sqapi-types.h" ++ + ''', + prefix=prefix, guard=guardname(h_file))) + + exprs = parse_schema(sys.stdin) + ++# to avoid header dependency hell, we always generate declarations ++# for built-in types in our header files and simply guard them ++fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL")) ++for typename in builtin_types: ++ fdecl.write(generate_declaration(typename, None, genlist=True, ++ builtin_type=True)) ++fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) ++ ++# ...this doesn't work for cases where we link in multiple objects that ++# have the functions defined, so we use -b option to provide control ++# over these cases ++if do_builtins: ++ fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF")) ++ for typename in builtin_types: ++ fdef.write(generate_visit_list(typename, None)) ++ fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF")) ++ + for expr in exprs: + if expr.has_key('type'): + ret = generate_visit_struct(expr) +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-schema-Use-BlockdevSnapshot-type-for-blockdev-s.patch b/SOURCES/kvm-qapi-schema-Use-BlockdevSnapshot-type-for-blockdev-s.patch new file mode 100644 index 0000000..859e508 --- /dev/null +++ b/SOURCES/kvm-qapi-schema-Use-BlockdevSnapshot-type-for-blockdev-s.patch @@ -0,0 +1,69 @@ +From 230096f8fe835dc7814028643bb6feaa08bda5c5 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:06 +0200 +Subject: [PATCH 15/38] qapi-schema: Use BlockdevSnapshot type for blockdev-snapshot-sync + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-16-git-send-email-kwolf@redhat.com> +Patchwork-id: 54202 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 15/32] qapi-schema: Use BlockdevSnapshot type for blockdev-snapshot-sync +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +We don't have to duplicate the definition any more now that we may refer +to a type instead. + +Signed-off-by: Kevin Wolf +Reviewed-by: Michael Roth +Signed-off-by: Luiz Capitulino +(cherry picked from commit 852ad1a900a4ae23514e1a53c86632543592c31b) + +Signed-off-by: Kevin Wolf +--- + qapi-schema.json | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 14 ++------------ + 1 files changed, 2 insertions(+), 12 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index 8dca641..3936337 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -1650,16 +1650,7 @@ + # + # Generates a synchronous snapshot of a block device. + # +-# @device: the name of the device to generate the snapshot from. +-# +-# @snapshot-file: the target of the new image. If the file exists, or if it +-# is a device, the snapshot will be created in the existing +-# file/device. If does not exist, a new file will be created. +-# +-# @format: #optional the format of the snapshot image, default is 'qcow2'. +-# +-# @mode: #optional whether and how QEMU should create a new image, default is +-# 'absolute-paths'. ++# For the arguments, see the documentation of BlockdevSnapshot. + # + # Returns: nothing on success + # If @device is not a valid block device, DeviceNotFound +@@ -1667,8 +1658,7 @@ + # Since 0.14.0 + ## + { 'command': 'blockdev-snapshot-sync', +- 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', +- '*mode': 'NewImageMode'} } ++ 'data': 'BlockdevSnapshot' } + + ## + # @human-monitor-command: +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-types-visit.py-Inheritance-for-structs.patch b/SOURCES/kvm-qapi-types-visit.py-Inheritance-for-structs.patch new file mode 100644 index 0000000..24eb27c --- /dev/null +++ b/SOURCES/kvm-qapi-types-visit.py-Inheritance-for-structs.patch @@ -0,0 +1,135 @@ +From e8b11ccb96a0a6ddbb039631511c91652e4d0efc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:08:58 +0100 +Subject: [PATCH 45/87] qapi-types/visit.py: Inheritance for structs + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-5-git-send-email-kwolf@redhat.com> +Patchwork-id: 55383 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 04/24] qapi-types/visit.py: Inheritance for structs +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +This introduces a new 'base' key for struct definitions that refers to +another struct type. On the JSON level, the fields of the base type are +included directly into the same namespace as the fields of the defined +type, like with unions. On the C level, a pointer to a struct of the +base type is included. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 622f557f5aaea1326c94ca4cddfa4eafeade3723) + +Signed-off-by: Kevin Wolf +--- + docs/qapi-code-gen.txt | 17 +++++++++++++++++ + scripts/qapi-types.py | 4 ++++ + scripts/qapi-visit.py | 18 ++++++++++++++++-- + 3 files changed, 37 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + docs/qapi-code-gen.txt | 17 +++++++++++++++++ + scripts/qapi-types.py | 4 ++++ + scripts/qapi-visit.py | 18 ++++++++++++++++-- + 3 files changed, 37 insertions(+), 2 deletions(-) + +diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt +index 0ce045c..91f44d0 100644 +--- a/docs/qapi-code-gen.txt ++++ b/docs/qapi-code-gen.txt +@@ -53,6 +53,23 @@ The use of '*' as a prefix to the name means the member is optional. Optional + members should always be added to the end of the dictionary to preserve + backwards compatibility. + ++ ++A complex type definition can specify another complex type as its base. ++In this case, the fields of the base type are included as top-level fields ++of the new complex type's dictionary in the QMP wire format. An example ++definition is: ++ ++ { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } } ++ { 'type': 'BlockdevOptionsGenericCOWFormat', ++ 'base': 'BlockdevOptionsGenericFormat', ++ 'data': { '*backing': 'str' } } ++ ++An example BlockdevOptionsGenericCOWFormat object on the wire could use ++both fields like this: ++ ++ { "file": "/some/place/my-image", ++ "backing": "/some/place/my-backing-file" } ++ + === Enumeration types === + + An enumeration type is a dictionary containing a single key whose value is a +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index ff60dfb..a0737a6 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -80,6 +80,7 @@ def generate_struct(expr): + structname = expr.get('type', "") + fieldname = expr.get('field', "") + members = expr['data'] ++ base = expr.get('base') + + ret = mcgen(''' + struct %(name)s +@@ -87,6 +88,9 @@ struct %(name)s + ''', + name=structname) + ++ if base: ++ ret += generate_struct_fields({'base': base}) ++ + ret += generate_struct_fields(members) + + if len(fieldname): +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index 43d902c..71004ae 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -17,7 +17,7 @@ import os + import getopt + import errno + +-def generate_visit_struct_fields(name, field_prefix, fn_prefix, members): ++def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None): + substructs = [] + ret = '' + full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix) +@@ -42,6 +42,19 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error * + name=name, full_name=full_name) + push_indent() + ++ if base: ++ ret += mcgen(''' ++visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err); ++if (!err) { ++ visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err); ++ error_propagate(errp, err); ++ err = NULL; ++ visit_end_implicit_struct(m, &err); ++} ++''', ++ c_prefix=c_var(field_prefix), ++ type=type_name(base), c_name=c_var('base')) ++ + for argname, argentry, optional, structured in parse_args(members): + if optional: + ret += mcgen(''' +@@ -124,8 +137,9 @@ def generate_visit_struct(expr): + + name = expr['type'] + members = expr['data'] ++ base = expr.get('base') + +- ret = generate_visit_struct_fields(name, "", "", members) ++ ret = generate_visit_struct_fields(name, "", "", members, base) + + ret += mcgen(''' + +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-types-visit.py-Pass-whole-expr-dict-for-structs.patch b/SOURCES/kvm-qapi-types-visit.py-Pass-whole-expr-dict-for-structs.patch new file mode 100644 index 0000000..465e80f --- /dev/null +++ b/SOURCES/kvm-qapi-types-visit.py-Pass-whole-expr-dict-for-structs.patch @@ -0,0 +1,95 @@ +From 9dbd79c3095d98b66d30893fd1ba8b98366e9d41 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:08:57 +0100 +Subject: [PATCH 44/87] qapi-types/visit.py: Pass whole expr dict for structs + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-4-git-send-email-kwolf@redhat.com> +Patchwork-id: 55382 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 03/24] qapi-types/visit.py: Pass whole expr dict for structs +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 14d36307ffdf949df9c1dd7f435e138b36f63bb0) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-types.py | 11 ++++++++--- + scripts/qapi-visit.py | 8 ++++++-- + 2 files changed, 14 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-types.py | 11 ++++++++--- + scripts/qapi-visit.py | 8 ++++++-- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index 8680160..ff60dfb 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -65,7 +65,7 @@ def generate_struct_fields(members): + c_name=c_var(argname)) + if structured: + push_indent() +- ret += generate_struct("", argname, argentry) ++ ret += generate_struct({ "field": argname, "data": argentry}) + pop_indent() + else: + ret += mcgen(''' +@@ -75,7 +75,12 @@ def generate_struct_fields(members): + + return ret + +-def generate_struct(structname, fieldname, members): ++def generate_struct(expr): ++ ++ structname = expr.get('type', "") ++ fieldname = expr.get('field', "") ++ members = expr['data'] ++ + ret = mcgen(''' + struct %(name)s + { +@@ -411,7 +416,7 @@ if do_builtins: + for expr in exprs: + ret = "\n" + if expr.has_key('type'): +- ret += generate_struct(expr['type'], "", expr['data']) + "\n" ++ ret += generate_struct(expr) + "\n" + ret += generate_type_cleanup_decl(expr['type'] + "List") + fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n") + ret += generate_type_cleanup_decl(expr['type']) +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index 367cf7a..43d902c 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -120,7 +120,11 @@ if (!err) { + ''') + return ret + +-def generate_visit_struct(name, members): ++def generate_visit_struct(expr): ++ ++ name = expr['type'] ++ members = expr['data'] ++ + ret = generate_visit_struct_fields(name, "", "", members) + + ret += mcgen(''' +@@ -448,7 +452,7 @@ exprs = parse_schema(sys.stdin) + + for expr in exprs: + if expr.has_key('type'): +- ret = generate_visit_struct(expr['type'], expr['data']) ++ ret = generate_visit_struct(expr) + ret += generate_visit_list(expr['type'], expr['data']) + fdef.write(ret) + +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch b/SOURCES/kvm-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch new file mode 100644 index 0000000..9198aa6 --- /dev/null +++ b/SOURCES/kvm-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch @@ -0,0 +1,63 @@ +From 8c58dddfb0bdd43600840ff14b03b42bacfea18c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:08:56 +0100 +Subject: [PATCH 43/87] qapi-types.py: Fix enum struct sizes on i686 + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-3-git-send-email-kwolf@redhat.com> +Patchwork-id: 55381 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 02/24] qapi-types.py: Fix enum struct sizes on i686 +Bugzilla: 978402 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz + +From: Cole Robinson + +Unlike other list types, enum wasn't adding any padding, which caused +a mismatch between the generated struct size and GenericList struct +size. More details in a678e26cbe89f7a27cbce794c2c2784571ee9d21 + +This crashed qemu if calling qmp query-tpm-types for example, which +upsets libvirt capabilities probing. Reproducer on i686: + +(sleep 5; printf '{"execute":"qmp_capabilities"}\n{"execute":"query-tpm-types"}\n') | ./i386-softmmu/qemu-system-i386 -S -nodefaults -nographic -M none -qmp stdio + +https://bugs.launchpad.net/qemu/+bug/1219207 + +Cc: qemu-stable@nongnu.org +Signed-off-by: Cole Robinson +Reviewed-by: Eric Blake +Tested-by: Richard W.M. Jones +Signed-off-by: Luiz Capitulino +(cherry picked from commit 02dc4bf5684d3fb46786fab2ecff98214b1df9fe) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-types.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-types.py | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index e9bd638..8680160 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -45,7 +45,10 @@ def generate_fwd_enum_struct(name, members): + return mcgen(''' + typedef struct %(name)sList + { +- %(name)s value; ++ union { ++ %(name)s value; ++ uint64_t padding; ++ }; + struct %(name)sList *next; + } %(name)sList; + ''', +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-types.py-Implement-base-for-unions.patch b/SOURCES/kvm-qapi-types.py-Implement-base-for-unions.patch new file mode 100644 index 0000000..7557ba7 --- /dev/null +++ b/SOURCES/kvm-qapi-types.py-Implement-base-for-unions.patch @@ -0,0 +1,102 @@ +From da3719ca3f47e716394f3a572f0f1403518a8442 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:07 +0200 +Subject: [PATCH 16/38] qapi-types.py: Implement 'base' for unions + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-17-git-send-email-kwolf@redhat.com> +Patchwork-id: 54203 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 16/32] qapi-types.py: Implement 'base' for unions +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +The new 'base' key in a union definition refers to a struct type, which +is inlined into the union definition and can represent fields common to +all kinds. + +For example the following schema definition... + + { 'type': 'BlockOptionsBase', 'data': { 'read-only': 'bool' } } + + { 'union': 'BlockOptions', + 'base': 'BlockOptionsBase', + 'data': { + 'raw': 'BlockOptionsRaw' + 'qcow2': 'BlockOptionsQcow2' + } } + +...would result in this generated C struct: + + struct BlockOptions + { + BlockOptionsKind kind; + union { + void *data; + BlockOptionsRaw * raw; + BlockOptionsQcow2 * qcow2; + }; + bool read_only; + }; + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit e2503f5e213e30e3e9a397d454a35c10b5bdc899) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-types.py | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-types.py | 16 ++++++++++++++-- + 1 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index 9e19920..c0684a7 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -131,7 +131,12 @@ typedef enum %(name)s + + return lookup_decl + enum_decl + +-def generate_union(name, typeinfo): ++def generate_union(expr): ++ ++ name = expr['union'] ++ typeinfo = expr['data'] ++ base = expr.get('base') ++ + ret = mcgen(''' + struct %(name)s + { +@@ -150,6 +155,13 @@ struct %(name)s + + ret += mcgen(''' + }; ++''') ++ ++ if base: ++ struct = find_struct(base) ++ ret += generate_struct_fields(struct['data']) ++ ++ ret += mcgen(''' + }; + ''') + +@@ -307,7 +319,7 @@ for expr in exprs: + ret += generate_type_cleanup_decl(expr['type']) + fdef.write(generate_type_cleanup(expr['type']) + "\n") + elif expr.has_key('union'): +- ret += generate_union(expr['union'], expr['data']) ++ ret += generate_union(expr) + ret += generate_type_cleanup_decl(expr['union'] + "List") + fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") + ret += generate_type_cleanup_decl(expr['union']) +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-types.py-Split-off-generate_struct_fields.patch b/SOURCES/kvm-qapi-types.py-Split-off-generate_struct_fields.patch new file mode 100644 index 0000000..3c18d9c --- /dev/null +++ b/SOURCES/kvm-qapi-types.py-Split-off-generate_struct_fields.patch @@ -0,0 +1,68 @@ +From 798796e641d7e1146b9d6679958f8264efd1494e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:08:55 +0100 +Subject: [PATCH 42/87] qapi-types.py: Split off generate_struct_fields() + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 55380 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 01/24] qapi-types.py: Split off generate_struct_fields() +Bugzilla: 978402 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 015370301fd90ea5d17522eba00ae2797569ce8b) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-types.py | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-types.py | 19 +++++++++++++------ + 1 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py +index 20f4bdf..e9bd638 100644 +--- a/scripts/qapi-types.py ++++ b/scripts/qapi-types.py +@@ -51,12 +51,8 @@ typedef struct %(name)sList + ''', + name=name) + +-def generate_struct(structname, fieldname, members): +- ret = mcgen(''' +-struct %(name)s +-{ +-''', +- name=structname) ++def generate_struct_fields(members): ++ ret = '' + + for argname, argentry, optional, structured in parse_args(members): + if optional: +@@ -74,6 +70,17 @@ struct %(name)s + ''', + c_type=c_type(argentry), c_name=c_var(argname)) + ++ return ret ++ ++def generate_struct(structname, fieldname, members): ++ ret = mcgen(''' ++struct %(name)s ++{ ++''', ++ name=structname) ++ ++ ret += generate_struct_fields(members) ++ + if len(fieldname): + fieldname = " " + fieldname + ret += mcgen(''' +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-visit.py-Implement-base-for-unions.patch b/SOURCES/kvm-qapi-visit.py-Implement-base-for-unions.patch new file mode 100644 index 0000000..e230894 --- /dev/null +++ b/SOURCES/kvm-qapi-visit.py-Implement-base-for-unions.patch @@ -0,0 +1,112 @@ +From f1567daa732a9f61641e6089525db0ae7f75aa06 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:09 +0200 +Subject: [PATCH 18/38] qapi-visit.py: Implement 'base' for unions + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-19-git-send-email-kwolf@redhat.com> +Patchwork-id: 54205 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 18/32] qapi-visit.py: Implement 'base' for unions +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This implements the visitor part of base types for unions. Parsed into +QMP, this example schema definition... + + { 'type': 'BlockOptionsBase', 'data': { 'read-only': 'bool' } } + { 'type': 'BlockOptionsQcow2, 'data': { 'lazy-refcounts': 'bool' } } + + { 'union': 'BlockOptions', + 'base': 'BlockOptionsBase', + 'data': { + 'raw': 'BlockOptionsRaw' + 'qcow2': 'BlockOptionsQcow2' + } } + +...would describe the following JSON object: + + { "type": "qcow2", + "read-only": true, + "data": { "lazy-refcounts": false } } + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 0aef92b90d24858eea1ebd52a51bc31563f1fb52) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-visit.py | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-visit.py | 30 +++++++++++++++++++++++++----- + 1 files changed, 25 insertions(+), 5 deletions(-) + +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index 5adc2af..be56ba4 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -151,7 +151,13 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e + ''', + name=name) + +-def generate_visit_union(name, members): ++def generate_visit_union(expr): ++ ++ name = expr['union'] ++ members = expr['data'] ++ ++ base = expr.get('base') ++ + ret = generate_visit_enum('%sKind' % name, members.keys()) + + ret += mcgen(''' +@@ -164,14 +170,28 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** + visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); + if (!err) { + if (obj && *obj) { +- visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); +- if (!err) { +- switch ((*obj)->kind) { + ''', + name=name) + ++ + push_indent() + push_indent() ++ push_indent() ++ ++ if base: ++ struct = find_struct(base) ++ push_indent() ++ ret += generate_visit_struct_fields("", struct['data']) ++ pop_indent() ++ ++ pop_indent() ++ ret += mcgen(''' ++ visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); ++ if (!err) { ++ switch ((*obj)->kind) { ++''', ++ name=name) ++ + for key in members: + ret += mcgen(''' + case %(abbrev)s_KIND_%(enum)s: +@@ -344,7 +364,7 @@ for expr in exprs: + ret = generate_declaration(expr['type'], expr['data']) + fdecl.write(ret) + elif expr.has_key('union'): +- ret = generate_visit_union(expr['union'], expr['data']) ++ ret = generate_visit_union(expr) + ret += generate_visit_list(expr['union'], expr['data']) + fdef.write(ret) + +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi-visit.py-Split-off-generate_visit_struct_fields.patch b/SOURCES/kvm-qapi-visit.py-Split-off-generate_visit_struct_fields.patch new file mode 100644 index 0000000..08938a4 --- /dev/null +++ b/SOURCES/kvm-qapi-visit.py-Split-off-generate_visit_struct_fields.patch @@ -0,0 +1,116 @@ +From 0c8fb6c71c02e202235933781430efac5c0d7314 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:08 +0200 +Subject: [PATCH 17/38] qapi-visit.py: Split off generate_visit_struct_fields() + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-18-git-send-email-kwolf@redhat.com> +Patchwork-id: 54204 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 17/32] qapi-visit.py: Split off generate_visit_struct_fields() +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit d131c897f3dea8b76d7a487af0f7f5f11d0500a3) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi-visit.py | 62 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 34 insertions(+), 28 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi-visit.py | 62 ++++++++++++++++++++++++++---------------------- + 1 files changed, 34 insertions(+), 28 deletions(-) + +diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py +index a276540..5adc2af 100644 +--- a/scripts/qapi-visit.py ++++ b/scripts/qapi-visit.py +@@ -17,34 +17,9 @@ import os + import getopt + import errno + +-def generate_visit_struct_body(field_prefix, name, members): +- ret = mcgen(''' +-if (!error_is_set(errp)) { +-''') +- push_indent() +- +- if len(field_prefix): +- field_prefix = field_prefix + "." +- ret += mcgen(''' +-Error **errp = &err; /* from outer scope */ +-Error *err = NULL; +-visit_start_struct(m, NULL, "", "%(name)s", 0, &err); +-''', +- name=name) +- else: +- ret += mcgen(''' +-Error *err = NULL; +-visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); +-''', +- name=name) ++def generate_visit_struct_fields(field_prefix, members): ++ ret = '' + +- ret += mcgen(''' +-if (!err) { +- if (!obj || *obj) { +-''') +- +- push_indent() +- push_indent() + for argname, argentry, optional, structured in parse_args(members): + if optional: + ret += mcgen(''' +@@ -72,9 +47,40 @@ visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", + visit_end_optional(m, &err); + ''') + +- pop_indent() ++ return ret ++ ++ ++def generate_visit_struct_body(field_prefix, name, members): ++ ret = mcgen(''' ++if (!error_is_set(errp)) { ++''') ++ push_indent() ++ ++ if len(field_prefix): ++ field_prefix = field_prefix + "." ++ ret += mcgen(''' ++Error **errp = &err; /* from outer scope */ ++Error *err = NULL; ++visit_start_struct(m, NULL, "", "%(name)s", 0, &err); ++''', ++ name=name) ++ else: ++ ret += mcgen(''' ++Error *err = NULL; ++visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); ++''', ++ name=name) ++ + ret += mcgen(''' ++if (!err) { ++ if (!obj || *obj) { ++''') ++ push_indent() ++ push_indent() + ++ ret += generate_visit_struct_fields(field_prefix, members) ++ pop_indent() ++ ret += mcgen(''' + error_propagate(errp, err); + err = NULL; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi.py-Allow-top-level-type-reference-for-command-d.patch b/SOURCES/kvm-qapi.py-Allow-top-level-type-reference-for-command-d.patch new file mode 100644 index 0000000..60629ec --- /dev/null +++ b/SOURCES/kvm-qapi.py-Allow-top-level-type-reference-for-command-d.patch @@ -0,0 +1,84 @@ +From 89a70ccf822a86d05efb34e50958de831a071d05 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:05 +0200 +Subject: [PATCH 14/38] qapi.py: Allow top-level type reference for command definitions + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-15-git-send-email-kwolf@redhat.com> +Patchwork-id: 54201 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 14/32] qapi.py: Allow top-level type reference for command definitions +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +If 'data' for a command definition isn't a dict, but a string, it is +taken as a (struct) type name and the fields of this struct are directly +used as parameters. + +This is useful for transactionable commands that can use the same type +definition for both the transaction action and the arguments of the +standalone command. + +Signed-off-by: Kevin Wolf +Reviewed-by: Michael Roth +Signed-off-by: Luiz Capitulino +(cherry picked from commit b35284ea207a0ae1c0b162344cdef2a83304befc) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi.py | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi.py | 19 +++++++++++++++++++ + 1 files changed, 19 insertions(+), 0 deletions(-) + +diff --git a/scripts/qapi.py b/scripts/qapi.py +index daedaea..0c3bd84 100644 +--- a/scripts/qapi.py ++++ b/scripts/qapi.py +@@ -100,11 +100,18 @@ def parse_schema(fp): + add_enum(expr_eval['enum']) + elif expr_eval.has_key('union'): + add_enum('%sKind' % expr_eval['union']) ++ elif expr_eval.has_key('type'): ++ add_struct(expr_eval) + exprs.append(expr_eval) + + return exprs + + def parse_args(typeinfo): ++ if isinstance(typeinfo, basestring): ++ struct = find_struct(typeinfo) ++ assert struct != None ++ typeinfo = struct['data'] ++ + for member in typeinfo: + argname = member + argentry = typeinfo[member] +@@ -174,6 +181,18 @@ def type_name(name): + return name + + enum_types = [] ++struct_types = [] ++ ++def add_struct(definition): ++ global struct_types ++ struct_types.append(definition) ++ ++def find_struct(name): ++ global struct_types ++ for struct in struct_types: ++ if struct['type'] == name: ++ return struct ++ return None + + def add_enum(name): + global enum_types +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi.py-Avoid-code-duplication.patch b/SOURCES/kvm-qapi.py-Avoid-code-duplication.patch new file mode 100644 index 0000000..4fefb9a --- /dev/null +++ b/SOURCES/kvm-qapi.py-Avoid-code-duplication.patch @@ -0,0 +1,81 @@ +From 4bd5352922b192e3442671b2015633720253a3e4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:04 +0200 +Subject: [PATCH 13/38] qapi.py: Avoid code duplication + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-14-git-send-email-kwolf@redhat.com> +Patchwork-id: 54200 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 13/32] qapi.py: Avoid code duplication +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +The code that interprets the read JSON expression and appends types to +the respective global variables was duplicated. We can avoid that by +splitting off the part that reads from the file. + +Signed-off-by: Kevin Wolf +Reviewed-by: Michael Roth +Signed-off-by: Luiz Capitulino +(cherry picked from commit bd9927fee4e63b451b4ef67a4c49729070d8b05d) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi.py | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi.py | 18 +++++++++--------- + 1 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/scripts/qapi.py b/scripts/qapi.py +index afc5f32..daedaea 100644 +--- a/scripts/qapi.py ++++ b/scripts/qapi.py +@@ -72,10 +72,8 @@ def parse(tokens): + def evaluate(string): + return parse(map(lambda x: x, tokenize(string)))[0] + +-def parse_schema(fp): +- exprs = [] ++def get_expr(fp): + expr = '' +- expr_eval = None + + for line in fp: + if line.startswith('#') or line == '\n': +@@ -84,18 +82,20 @@ def parse_schema(fp): + if line.startswith(' '): + expr += line + elif expr: +- expr_eval = evaluate(expr) +- if expr_eval.has_key('enum'): +- add_enum(expr_eval['enum']) +- elif expr_eval.has_key('union'): +- add_enum('%sKind' % expr_eval['union']) +- exprs.append(expr_eval) ++ yield expr + expr = line + else: + expr += line + + if expr: ++ yield expr ++ ++def parse_schema(fp): ++ exprs = [] ++ ++ for expr in get_expr(fp): + expr_eval = evaluate(expr) ++ + if expr_eval.has_key('enum'): + add_enum(expr_eval['enum']) + elif expr_eval.has_key('union'): +-- +1.7.1 + diff --git a/SOURCES/kvm-qapi.py-Maintain-a-list-of-union-types.patch b/SOURCES/kvm-qapi.py-Maintain-a-list-of-union-types.patch new file mode 100644 index 0000000..060320c --- /dev/null +++ b/SOURCES/kvm-qapi.py-Maintain-a-list-of-union-types.patch @@ -0,0 +1,71 @@ +From 7fa89ebb4c2f761a8df462cf9ffcb6174b4a4a26 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:14 +0200 +Subject: [PATCH 23/38] qapi.py: Maintain a list of union types + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-24-git-send-email-kwolf@redhat.com> +Patchwork-id: 54210 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 23/32] qapi.py: Maintain a list of union types +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit ea66c6d8819c8fc5f73a28554992be64e5399fed) + +Signed-off-by: Kevin Wolf +--- + scripts/qapi.py | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + scripts/qapi.py | 13 +++++++++++++ + 1 files changed, 13 insertions(+), 0 deletions(-) + +diff --git a/scripts/qapi.py b/scripts/qapi.py +index 0c3bd84..03c42a9 100644 +--- a/scripts/qapi.py ++++ b/scripts/qapi.py +@@ -99,6 +99,7 @@ def parse_schema(fp): + if expr_eval.has_key('enum'): + add_enum(expr_eval['enum']) + elif expr_eval.has_key('union'): ++ add_union(expr_eval) + add_enum('%sKind' % expr_eval['union']) + elif expr_eval.has_key('type'): + add_struct(expr_eval) +@@ -182,6 +183,7 @@ def type_name(name): + + enum_types = [] + struct_types = [] ++union_types = [] + + def add_struct(definition): + global struct_types +@@ -194,6 +196,17 @@ def find_struct(name): + return struct + return None + ++def add_union(definition): ++ global union_types ++ union_types.append(definition) ++ ++def find_union(name): ++ global union_types ++ for union in union_types: ++ if union['union'] == name: ++ return union ++ return None ++ + def add_enum(name): + global enum_types + enum_types.append(name) +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Add-corrupt-bit.patch b/SOURCES/kvm-qcow2-Add-corrupt-bit.patch new file mode 100644 index 0000000..79c7bc9 --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-corrupt-bit.patch @@ -0,0 +1,234 @@ +From 0e79ef6691f77a7c0da31dff9276b6dad42441a0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:31:59 +0100 +Subject: [PATCH 06/87] qcow2: Add corrupt bit + +RH-Author: Max Reitz +Message-id: <1383604354-12743-9-git-send-email-mreitz@redhat.com> +Patchwork-id: 55308 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 08/43] qcow2: Add corrupt bit +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +This adds an incompatible bit indicating corruption to qcow2. Any image +with this bit set may not be written to unless for repairing (and +subsequently clearing the bit if the repair has been successful). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 69c98726537627e708abb8fcb33e3a2b10e40bf1) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 7 ++++++- + docs/specs/qcow2.txt | 7 ++++++- + tests/qemu-iotests/031.out | 12 ++++++------ + tests/qemu-iotests/036.out | 2 +- + 5 files changed, 66 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 7 +++++- + docs/specs/qcow2.txt | 7 +++++- + tests/qemu-iotests/031.out | 12 +++++----- + tests/qemu-iotests/036.out | 2 +- + 5 files changed, 66 insertions(+), 9 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index c2728c9..aa9dd23 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -272,6 +272,37 @@ static int qcow2_mark_clean(BlockDriverState *bs) + return 0; + } + ++/* ++ * Marks the image as corrupt. ++ */ ++int qcow2_mark_corrupt(BlockDriverState *bs) ++{ ++ BDRVQcowState *s = bs->opaque; ++ ++ s->incompatible_features |= QCOW2_INCOMPAT_CORRUPT; ++ return qcow2_update_header(bs); ++} ++ ++/* ++ * Marks the image as consistent, i.e., unsets the corrupt bit, and flushes ++ * before if necessary. ++ */ ++int qcow2_mark_consistent(BlockDriverState *bs) ++{ ++ BDRVQcowState *s = bs->opaque; ++ ++ if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) { ++ int ret = bdrv_flush(bs); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ s->incompatible_features &= ~QCOW2_INCOMPAT_CORRUPT; ++ return qcow2_update_header(bs); ++ } ++ return 0; ++} ++ + static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, + BdrvCheckMode fix) + { +@@ -402,6 +433,17 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) + goto fail; + } + ++ if (s->incompatible_features & QCOW2_INCOMPAT_CORRUPT) { ++ /* Corrupt images may not be written to unless they are being repaired ++ */ ++ if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) { ++ error_report("qcow2: Image is corrupt; cannot be opened " ++ "read/write."); ++ ret = -EACCES; ++ goto fail; ++ } ++ } ++ + /* Check support for various header values */ + if (header.refcount_order != 4) { + report_unsupported(bs, "%d bit reference counts", +@@ -1140,6 +1182,11 @@ int qcow2_update_header(BlockDriverState *bs) + .name = "dirty bit", + }, + { ++ .type = QCOW2_FEAT_TYPE_INCOMPATIBLE, ++ .bit = QCOW2_INCOMPAT_CORRUPT_BITNR, ++ .name = "corrupt bit", ++ }, ++ { + .type = QCOW2_FEAT_TYPE_COMPATIBLE, + .bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR, + .name = "lazy refcounts", +diff --git a/block/qcow2.h b/block/qcow2.h +index dba9771..4297487 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -119,9 +119,12 @@ enum { + /* Incompatible feature bits */ + enum { + QCOW2_INCOMPAT_DIRTY_BITNR = 0, ++ QCOW2_INCOMPAT_CORRUPT_BITNR = 1, + QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR, ++ QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR, + +- QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY, ++ QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY ++ | QCOW2_INCOMPAT_CORRUPT, + }; + + /* Compatible feature bits */ +@@ -361,6 +364,8 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, + int64_t sector_num, int nb_sectors); + + int qcow2_mark_dirty(BlockDriverState *bs); ++int qcow2_mark_corrupt(BlockDriverState *bs); ++int qcow2_mark_consistent(BlockDriverState *bs); + int qcow2_update_header(BlockDriverState *bs); + + /* qcow2-refcount.c functions */ +diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt +index 36a559d..33eca36 100644 +--- a/docs/specs/qcow2.txt ++++ b/docs/specs/qcow2.txt +@@ -80,7 +80,12 @@ in the description of a field. + tables to repair refcounts before accessing the + image. + +- Bits 1-63: Reserved (set to 0) ++ Bit 1: Corrupt bit. If this bit is set then any data ++ structure may be corrupt and the image must not ++ be written to (unless for regaining ++ consistency). ++ ++ Bits 2-63: Reserved (set to 0) + + 80 - 87: compatible_features + Bitmask of compatible features. An implementation can +diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out +index 796c993..a943344 100644 +--- a/tests/qemu-iotests/031.out ++++ b/tests/qemu-iotests/031.out +@@ -54,7 +54,7 @@ header_length 72 + + Header extension: + magic 0x6803f857 +-length 96 ++length 144 + data + + Header extension: +@@ -68,7 +68,7 @@ No errors were found on the image. + + magic 0x514649fb + version 2 +-backing_file_offset 0xf8 ++backing_file_offset 0x128 + backing_file_size 0x17 + cluster_bits 16 + size 67108864 +@@ -92,7 +92,7 @@ data 'host_device' + + Header extension: + magic 0x6803f857 +-length 96 ++length 144 + data + + Header extension: +@@ -155,7 +155,7 @@ header_length 104 + + Header extension: + magic 0x6803f857 +-length 96 ++length 144 + data + + Header extension: +@@ -169,7 +169,7 @@ No errors were found on the image. + + magic 0x514649fb + version 3 +-backing_file_offset 0x118 ++backing_file_offset 0x148 + backing_file_size 0x17 + cluster_bits 16 + size 67108864 +@@ -193,7 +193,7 @@ data 'host_device' + + Header extension: + magic 0x6803f857 +-length 96 ++length 144 + data + + Header extension: +diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out +index 063ca22..55a3e6e 100644 +--- a/tests/qemu-iotests/036.out ++++ b/tests/qemu-iotests/036.out +@@ -46,7 +46,7 @@ header_length 104 + + Header extension: + magic 0x6803f857 +-length 96 ++length 144 + data + + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Add-more-overlap-check-bitmask-macros.patch b/SOURCES/kvm-qcow2-Add-more-overlap-check-bitmask-macros.patch new file mode 100644 index 0000000..a7316da --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-more-overlap-check-bitmask-macros.patch @@ -0,0 +1,66 @@ +From cd63525d205eda67c64d0838592b819d7f73529f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:33 +0100 +Subject: [PATCH 40/87] qcow2: Add more overlap check bitmask macros + +RH-Author: Max Reitz +Message-id: <1383604354-12743-43-git-send-email-mreitz@redhat.com> +Patchwork-id: 55342 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 42/43] qcow2: Add more overlap check bitmask macros +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Introduces the macros QCOW2_OL_CONSTANT and QCOW2_OL_ALL in addition to +the already existing QCOW2_OL_CACHED, signifying all metadata overlap +checks that can be performed in constant time (regardless of image size +etc.) and truly all available overlap checks, respectively. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 4a273c398b0c96985d56fed8156e19876b2e3c9e) + +Signed-off-by: Max Reitz +--- + block/qcow2.h | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.h | 14 +++++++++++--- + 1 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/block/qcow2.h b/block/qcow2.h +index 1bba3ed..e4c140c 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -325,11 +325,19 @@ typedef enum QCow2MetadataOverlap { + QCOW2_OL_INACTIVE_L2 = (1 << QCOW2_OL_INACTIVE_L2_BITNR), + } QCow2MetadataOverlap; + ++/* Perform all overlap checks which can be done in constant time */ ++#define QCOW2_OL_CONSTANT \ ++ (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_REFCOUNT_TABLE | \ ++ QCOW2_OL_SNAPSHOT_TABLE) ++ + /* Perform all overlap checks which don't require disk access */ + #define QCOW2_OL_CACHED \ +- (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_ACTIVE_L2 | \ +- QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \ +- QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1) ++ (QCOW2_OL_CONSTANT | QCOW2_OL_ACTIVE_L2 | QCOW2_OL_REFCOUNT_BLOCK | \ ++ QCOW2_OL_INACTIVE_L1) ++ ++/* Perform all overlap checks */ ++#define QCOW2_OL_ALL \ ++ (QCOW2_OL_CACHED | QCOW2_OL_INACTIVE_L2) + + #define L1E_OFFSET_MASK 0x00ffffffffffff00ULL + #define L2E_OFFSET_MASK 0x00ffffffffffff00ULL +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Add-overlap-check-options.patch b/SOURCES/kvm-qcow2-Add-overlap-check-options.patch new file mode 100644 index 0000000..5afb426 --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-overlap-check-options.patch @@ -0,0 +1,116 @@ +From 08a3a60a9a3cdd4d67e858981e4446d8f1d31fe4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:31 +0100 +Subject: [PATCH 38/87] qcow2: Add overlap-check options + +RH-Author: Max Reitz +Message-id: <1383604354-12743-41-git-send-email-mreitz@redhat.com> +Patchwork-id: 55340 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 40/43] qcow2: Add overlap-check options +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Add runtime options to tune the overlap checks to be performed before +write accesses. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 05de7e86cab3ed3830de38b38b39bbc711bc1158) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 9 +++++++++ + 2 files changed, 55 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 9 +++++++++ + 2 files changed, 55 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 157361f..c47286f 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -354,6 +354,52 @@ static QemuOptsList qcow2_runtime_opts = { + .type = QEMU_OPT_BOOL, + .help = "Generate discard requests when other clusters are freed", + }, ++ { ++ .name = QCOW2_OPT_OVERLAP, ++ .type = QEMU_OPT_STRING, ++ .help = "Selects which overlap checks to perform from a range of " ++ "templates (none, constant, cached, all)", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_MAIN_HEADER, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into the main qcow2 header", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_ACTIVE_L1, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into the active L1 table", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_ACTIVE_L2, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into an active L2 table", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into the refcount table", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into a refcount block", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into the snapshot table", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_INACTIVE_L1, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into an inactive L1 table", ++ }, ++ { ++ .name = QCOW2_OPT_OVERLAP_INACTIVE_L2, ++ .type = QEMU_OPT_BOOL, ++ .help = "Check for unintended writes into an inactive L2 table", ++ }, + { /* end of list */ } + }, + }; +diff --git a/block/qcow2.h b/block/qcow2.h +index d1fd91b..1bba3ed 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -63,6 +63,15 @@ + #define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request" + #define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot" + #define QCOW2_OPT_DISCARD_OTHER "pass-discard-other" ++#define QCOW2_OPT_OVERLAP "overlap-check" ++#define QCOW2_OPT_OVERLAP_MAIN_HEADER "overlap-check.main-header" ++#define QCOW2_OPT_OVERLAP_ACTIVE_L1 "overlap-check.active-l1" ++#define QCOW2_OPT_OVERLAP_ACTIVE_L2 "overlap-check.active-l2" ++#define QCOW2_OPT_OVERLAP_REFCOUNT_TABLE "overlap-check.refcount-table" ++#define QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK "overlap-check.refcount-block" ++#define QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE "overlap-check.snapshot-table" ++#define QCOW2_OPT_OVERLAP_INACTIVE_L1 "overlap-check.inactive-l1" ++#define QCOW2_OPT_OVERLAP_INACTIVE_L2 "overlap-check.inactive-l2" + + typedef struct QCowHeader { + uint32_t magic; +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Add-refcount-update-reason-to-all-callers.patch b/SOURCES/kvm-qcow2-Add-refcount-update-reason-to-all-callers.patch new file mode 100644 index 0000000..1aa98f4 --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-refcount-update-reason-to-all-callers.patch @@ -0,0 +1,375 @@ +From 2e86e4a584cd9054a99d6bb8d3d4d7e8878bff4a Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:00 +0200 +Subject: [PATCH 09/38] qcow2: Add refcount update reason to all callers + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-10-git-send-email-kwolf@redhat.com> +Patchwork-id: 54198 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 09/32] qcow2: Add refcount update reason to all callers +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This adds a refcount update reason to all callers of update_refcounts(), +so that a follow-up patch can use this information to decide whether +clusters that reach a refcount of 0 should be discarded in the image +file. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 6cfcb9b8b91d303ab51b78623f2299b5288d2d51) + +Signed-off-by: Kevin Wolf +--- + block/qcow2-cluster.c | 19 +++++++++++------ + block/qcow2-refcount.c | 55 +++++++++++++++++++++++++++++++------------------- + block/qcow2-snapshot.c | 6 ++++-- + block/qcow2.c | 3 ++- + block/qcow2.h | 16 ++++++++++++--- + 5 files changed, 66 insertions(+), 33 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 19 +++++++++++----- + block/qcow2-refcount.c | 55 +++++++++++++++++++++++++++++------------------ + block/qcow2-snapshot.c | 6 +++- + block/qcow2.c | 3 +- + block/qcow2.h | 16 +++++++++++-- + 5 files changed, 66 insertions(+), 33 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 76f30e5..3191d6b 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -98,14 +98,16 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + goto fail; + } + g_free(s->l1_table); +- qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t)); ++ qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t), ++ QCOW2_DISCARD_OTHER); + s->l1_table_offset = new_l1_table_offset; + s->l1_table = new_l1_table; + s->l1_size = new_l1_size; + return 0; + fail: + g_free(new_l1_table); +- qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2); ++ qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2, ++ QCOW2_DISCARD_OTHER); + return ret; + } + +@@ -548,7 +550,8 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, + + /* Then decrease the refcount of the old table */ + if (l2_offset) { +- qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t)); ++ qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t), ++ QCOW2_DISCARD_OTHER); + } + } + +@@ -715,10 +718,14 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) + /* + * If this was a COW, we need to decrease the refcount of the old cluster. + * Also flush bs->file to get the right order for L2 and refcount update. ++ * ++ * Don't discard clusters that reach a refcount of 0 (e.g. compressed ++ * clusters), the next write will reuse them anyway. + */ + if (j != 0) { + for (i = 0; i < j; i++) { +- qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1); ++ qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1, ++ QCOW2_DISCARD_NEVER); + } + } + +@@ -1339,7 +1346,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_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); + } + + ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); +@@ -1415,7 +1422,7 @@ static int zero_single_l2(BlockDriverState *bs, uint64_t offset, + qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table); + if (old_offset & QCOW_OFLAG_COMPRESSED) { + l2_table[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO); +- qcow2_free_any_clusters(bs, old_offset, 1); ++ qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST); + } else { + l2_table[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO); + } +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index b32738f..6d35e49 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -29,7 +29,7 @@ + static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size); + static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + int64_t offset, int64_t length, +- int addend); ++ int addend, enum qcow2_discard_type type); + + + /*********************************************************/ +@@ -235,7 +235,8 @@ static int alloc_refcount_block(BlockDriverState *bs, + } else { + /* Described somewhere else. This can recurse at most twice before we + * arrive at a block that describes itself. */ +- ret = update_refcount(bs, new_block, s->cluster_size, 1); ++ ret = update_refcount(bs, new_block, s->cluster_size, 1, ++ QCOW2_DISCARD_NEVER); + if (ret < 0) { + goto fail_block; + } +@@ -399,7 +400,8 @@ static int alloc_refcount_block(BlockDriverState *bs, + + /* Free old table. Remember, we must not change free_cluster_index */ + uint64_t old_free_cluster_index = s->free_cluster_index; +- qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t)); ++ qcow2_free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t), ++ QCOW2_DISCARD_OTHER); + s->free_cluster_index = old_free_cluster_index; + + ret = load_refcount_block(bs, new_block, (void**) refcount_block); +@@ -420,7 +422,7 @@ fail_block: + + /* XXX: cache several refcount block clusters ? */ + static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, +- int64_t offset, int64_t length, int addend) ++ int64_t offset, int64_t length, int addend, enum qcow2_discard_type type) + { + BDRVQcowState *s = bs->opaque; + int64_t start, last, cluster_offset; +@@ -506,7 +508,8 @@ fail: + */ + if (ret < 0) { + int dummy; +- dummy = update_refcount(bs, offset, cluster_offset - offset, -addend); ++ dummy = update_refcount(bs, offset, cluster_offset - offset, -addend, ++ QCOW2_DISCARD_NEVER); + (void)dummy; + } + +@@ -522,12 +525,14 @@ fail: + */ + static int update_cluster_refcount(BlockDriverState *bs, + int64_t cluster_index, +- int addend) ++ int addend, ++ enum qcow2_discard_type type) + { + BDRVQcowState *s = bs->opaque; + int ret; + +- ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend); ++ ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend, ++ type); + if (ret < 0) { + return ret; + } +@@ -579,7 +584,7 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size) + return offset; + } + +- ret = update_refcount(bs, offset, size, 1); ++ ret = update_refcount(bs, offset, size, 1, QCOW2_DISCARD_NEVER); + if (ret < 0) { + return ret; + } +@@ -611,7 +616,8 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, + old_free_cluster_index = s->free_cluster_index; + s->free_cluster_index = cluster_index + i; + +- ret = update_refcount(bs, offset, i << s->cluster_bits, 1); ++ ret = update_refcount(bs, offset, i << s->cluster_bits, 1, ++ QCOW2_DISCARD_NEVER); + if (ret < 0) { + return ret; + } +@@ -649,7 +655,8 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) + if (free_in_cluster == 0) + s->free_byte_offset = 0; + if ((offset & (s->cluster_size - 1)) != 0) +- update_cluster_refcount(bs, offset >> s->cluster_bits, 1); ++ update_cluster_refcount(bs, offset >> s->cluster_bits, 1, ++ QCOW2_DISCARD_NEVER); + } else { + offset = qcow2_alloc_clusters(bs, s->cluster_size); + if (offset < 0) { +@@ -659,7 +666,8 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) + if ((cluster_offset + s->cluster_size) == offset) { + /* we are lucky: contiguous data */ + offset = s->free_byte_offset; +- update_cluster_refcount(bs, offset >> s->cluster_bits, 1); ++ update_cluster_refcount(bs, offset >> s->cluster_bits, 1, ++ QCOW2_DISCARD_NEVER); + s->free_byte_offset += size; + } else { + s->free_byte_offset = offset; +@@ -676,12 +684,13 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size) + } + + void qcow2_free_clusters(BlockDriverState *bs, +- int64_t offset, int64_t size) ++ int64_t offset, int64_t size, ++ enum qcow2_discard_type type) + { + int ret; + + BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_FREE); +- ret = update_refcount(bs, offset, size, -1); ++ ret = update_refcount(bs, offset, size, -1, type); + if (ret < 0) { + fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret)); + /* TODO Remember the clusters to free them later and avoid leaking */ +@@ -692,8 +701,8 @@ void qcow2_free_clusters(BlockDriverState *bs, + * Free a cluster using its L2 entry (handles clusters of all types, e.g. + * normal cluster, compressed cluster, etc.) + */ +-void qcow2_free_any_clusters(BlockDriverState *bs, +- uint64_t l2_entry, int nb_clusters) ++void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, ++ int nb_clusters, enum qcow2_discard_type type) + { + BDRVQcowState *s = bs->opaque; + +@@ -705,12 +714,12 @@ void qcow2_free_any_clusters(BlockDriverState *bs, + s->csize_mask) + 1; + qcow2_free_clusters(bs, + (l2_entry & s->cluster_offset_mask) & ~511, +- nb_csectors * 512); ++ nb_csectors * 512, type); + } + break; + case QCOW2_CLUSTER_NORMAL: + qcow2_free_clusters(bs, l2_entry & L2E_OFFSET_MASK, +- nb_clusters << s->cluster_bits); ++ nb_clusters << s->cluster_bits, type); + break; + case QCOW2_CLUSTER_UNALLOCATED: + case QCOW2_CLUSTER_ZERO: +@@ -785,7 +794,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + int ret; + ret = update_refcount(bs, + (offset & s->cluster_offset_mask) & ~511, +- nb_csectors * 512, addend); ++ nb_csectors * 512, addend, ++ QCOW2_DISCARD_SNAPSHOT); + if (ret < 0) { + goto fail; + } +@@ -795,7 +805,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + } else { + uint64_t cluster_index = (offset & L2E_OFFSET_MASK) >> s->cluster_bits; + if (addend != 0) { +- refcount = update_cluster_refcount(bs, cluster_index, addend); ++ refcount = update_cluster_refcount(bs, cluster_index, addend, ++ QCOW2_DISCARD_SNAPSHOT); + } else { + refcount = get_refcount(bs, cluster_index); + } +@@ -827,7 +838,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + + + if (addend != 0) { +- refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend); ++ refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend, ++ QCOW2_DISCARD_SNAPSHOT); + } else { + refcount = get_refcount(bs, l2_offset >> s->cluster_bits); + } +@@ -1253,7 +1265,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + + if (num_fixed) { + ret = update_refcount(bs, i << s->cluster_bits, 1, +- refcount2 - refcount1); ++ refcount2 - refcount1, ++ QCOW2_DISCARD_ALWAYS); + if (ret >= 0) { + (*num_fixed)++; + continue; +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index 992a5c8..0caac90 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -262,7 +262,8 @@ static int qcow2_write_snapshots(BlockDriverState *bs) + } + + /* free the old snapshot table */ +- qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size); ++ qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size, ++ QCOW2_DISCARD_SNAPSHOT); + s->snapshots_offset = snapshots_offset; + s->snapshots_size = snapshots_size; + return 0; +@@ -569,7 +570,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) + if (ret < 0) { + return ret; + } +- qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t)); ++ qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t), ++ QCOW2_DISCARD_SNAPSHOT); + + /* must update the copied flag on the current cluster offsets */ + ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0); +diff --git a/block/qcow2.c b/block/qcow2.c +index 0fa5cb2..e28ea47 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1196,7 +1196,8 @@ static int preallocate(BlockDriverState *bs) + + ret = qcow2_alloc_cluster_link_l2(bs, meta); + if (ret < 0) { +- qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters); ++ qcow2_free_any_clusters(bs, meta->alloc_offset, meta->nb_clusters, ++ QCOW2_DISCARD_NEVER); + return ret; + } + +diff --git a/block/qcow2.h b/block/qcow2.h +index 6959c6a..64a6479 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -129,6 +129,15 @@ enum { + QCOW2_COMPAT_FEAT_MASK = QCOW2_COMPAT_LAZY_REFCOUNTS, + }; + ++enum qcow2_discard_type { ++ QCOW2_DISCARD_NEVER = 0, ++ QCOW2_DISCARD_ALWAYS, ++ QCOW2_DISCARD_REQUEST, ++ QCOW2_DISCARD_SNAPSHOT, ++ QCOW2_DISCARD_OTHER, ++ QCOW2_DISCARD_MAX ++}; ++ + typedef struct Qcow2Feature { + uint8_t type; + uint8_t bit; +@@ -349,9 +358,10 @@ int qcow2_alloc_clusters_at(BlockDriverState *bs, uint64_t offset, + int nb_clusters); + int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size); + void qcow2_free_clusters(BlockDriverState *bs, +- int64_t offset, int64_t size); +-void qcow2_free_any_clusters(BlockDriverState *bs, +- uint64_t cluster_offset, int nb_clusters); ++ int64_t offset, int64_t size, ++ enum qcow2_discard_type type); ++void qcow2_free_any_clusters(BlockDriverState *bs, uint64_t l2_entry, ++ int nb_clusters, enum qcow2_discard_type type); + + int qcow2_update_snapshot_refcount(BlockDriverState *bs, + int64_t l1_table_offset, int l1_size, int addend); +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Add-support-for-ImageInfoSpecific.patch b/SOURCES/kvm-qcow2-Add-support-for-ImageInfoSpecific.patch new file mode 100644 index 0000000..b6d202f --- /dev/null +++ b/SOURCES/kvm-qcow2-Add-support-for-ImageInfoSpecific.patch @@ -0,0 +1,122 @@ +From 42d65e8b2ebd637035fd3ccb5306cbdd37808cd3 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:37 +0100 +Subject: [PATCH 80/87] qcow2: Add support for ImageInfoSpecific + +RH-Author: Max Reitz +Message-id: <1383756824-6921-15-git-send-email-mreitz@redhat.com> +Patchwork-id: 55569 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 14/21] qcow2: Add support for ImageInfoSpecific +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +Add a new ImageInfoSpecificQCow2 type as a subtype of ImageInfoSpecific. +This contains the compatibility level as a string and an optional +lazy_refcounts boolean (optional means mandatory for compat >= 1.1 and +not available for compat == 0.10). + +Also, add qcow2_get_specific_info, which returns this information. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 37764dfb71c4d0d058b71ba33340c6beab7d5a66) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 28 ++++++++++++++++++++++++++++ + qapi-schema.json | 16 ++++++++++++++++ + 2 files changed, 44 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 28 ++++++++++++++++++++++++++++ + qapi-schema.json | 16 ++++++++++++++++ + 2 files changed, 44 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 01b535d..f852d64 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1889,6 +1889,33 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) + return 0; + } + ++static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs) ++{ ++ BDRVQcowState *s = bs->opaque; ++ ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1); ++ ++ *spec_info = (ImageInfoSpecific){ ++ .kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2, ++ { ++ .qcow2 = g_new(ImageInfoSpecificQCow2, 1), ++ }, ++ }; ++ if (s->qcow_version == 2) { ++ *spec_info->qcow2 = (ImageInfoSpecificQCow2){ ++ .compat = g_strdup("0.10"), ++ }; ++ } else if (s->qcow_version == 3) { ++ *spec_info->qcow2 = (ImageInfoSpecificQCow2){ ++ .compat = g_strdup("1.1"), ++ .lazy_refcounts = s->compatible_features & ++ QCOW2_COMPAT_LAZY_REFCOUNTS, ++ .has_lazy_refcounts = true, ++ }; ++ } ++ ++ return spec_info; ++} ++ + #if 0 + static void dump_refcounts(BlockDriverState *bs) + { +@@ -2024,6 +2051,7 @@ static BlockDriver bdrv_qcow2 = { + .bdrv_snapshot_list = qcow2_snapshot_list, + .bdrv_snapshot_load_tmp = qcow2_snapshot_load_tmp, + .bdrv_get_info = qcow2_get_info, ++ .bdrv_get_specific_info = qcow2_get_specific_info, + + .bdrv_save_vmstate = qcow2_save_vmstate, + .bdrv_load_vmstate = qcow2_load_vmstate, +diff --git a/qapi-schema.json b/qapi-schema.json +index 934ac7f..3c00ddd 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -210,6 +210,21 @@ + 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } } + + ## ++# @ImageInfoSpecificQCow2: ++# ++# @compat: compatibility level ++# ++# @lazy-refcounts: #optional on or off; only valid for compat >= 1.1 ++# ++# Since: 1.7 ++## ++{ 'type': 'ImageInfoSpecificQCow2', ++ 'data': { ++ 'compat': 'str', ++ '*lazy-refcounts': 'bool' ++ } } ++ ++## + # @ImageInfoSpecific: + # + # A discriminated record of image format specific information structures. +@@ -219,6 +234,7 @@ + + { 'union': 'ImageInfoSpecific', + 'data': { ++ 'qcow2': 'ImageInfoSpecificQCow2' + } } + + ## +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Array-assigning-options-to-OL-check-bits.patch b/SOURCES/kvm-qcow2-Array-assigning-options-to-OL-check-bits.patch new file mode 100644 index 0000000..68cea27 --- /dev/null +++ b/SOURCES/kvm-qcow2-Array-assigning-options-to-OL-check-bits.patch @@ -0,0 +1,59 @@ +From 154566a3a7e0ef3a32650952a79031c8e5c5489c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:32 +0100 +Subject: [PATCH 39/87] qcow2: Array assigning options to OL check bits + +RH-Author: Max Reitz +Message-id: <1383604354-12743-42-git-send-email-mreitz@redhat.com> +Patchwork-id: 55341 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 41/43] qcow2: Array assigning options to OL check bits +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Add an array which assigns the option string to its corresponding +overlap check bit. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 4092e99d935fe26fd53631cc9e170f9a19e3ee4a) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 11 +++++++++++ + 1 files changed, 11 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index c47286f..b6f300d 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -404,6 +404,17 @@ static QemuOptsList qcow2_runtime_opts = { + }, + }; + ++static const char *overlap_bool_option_names[QCOW2_OL_MAX_BITNR] = { ++ [QCOW2_OL_MAIN_HEADER_BITNR] = QCOW2_OPT_OVERLAP_MAIN_HEADER, ++ [QCOW2_OL_ACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L1, ++ [QCOW2_OL_ACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_ACTIVE_L2, ++ [QCOW2_OL_REFCOUNT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_TABLE, ++ [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = QCOW2_OPT_OVERLAP_REFCOUNT_BLOCK, ++ [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = QCOW2_OPT_OVERLAP_SNAPSHOT_TABLE, ++ [QCOW2_OL_INACTIVE_L1_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L1, ++ [QCOW2_OL_INACTIVE_L2_BITNR] = QCOW2_OPT_OVERLAP_INACTIVE_L2, ++}; ++ + static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + Error **errp) + { +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Batch-discards.patch b/SOURCES/kvm-qcow2-Batch-discards.patch new file mode 100644 index 0000000..0a365fc --- /dev/null +++ b/SOURCES/kvm-qcow2-Batch-discards.patch @@ -0,0 +1,272 @@ +From 766239ec3a7be7b8bf250a677e478773ac1b96dd Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:02 +0200 +Subject: [PATCH 11/38] qcow2: Batch discards + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-12-git-send-email-kwolf@redhat.com> +Patchwork-id: 54199 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 11/32] qcow2: Batch discards +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This optimises the discard operation for freed clusters by batching +discard requests (both snapshot deletion and bdrv_discard end up +updating the refcounts cluster by cluster). + +Note that we don't discard asynchronously, but keep s->lock held. This +is to avoid that a freed cluster is reallocated and written to while the +discard is still in flight. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 0b919fae31f4f80f78ebeab8388dc3a03cc5e4ed) + +Signed-off-by: Kevin Wolf +--- + block/qcow2-cluster.c | 22 +++++++++++--- + block/qcow2-refcount.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++-- + block/qcow2.c | 1 + + block/qcow2.h | 11 +++++++ + 4 files changed, 109 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 22 ++++++++++-- + block/qcow2-refcount.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-- + block/qcow2.c | 1 + + block/qcow2.h | 11 ++++++ + 4 files changed, 109 insertions(+), 7 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 3191d6b..cca76d4 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -1377,18 +1377,25 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset, + + nb_clusters = size_to_clusters(s, end_offset - offset); + ++ s->cache_discards = true; ++ + /* Each L2 table is handled by its own loop iteration */ + while (nb_clusters > 0) { + ret = discard_single_l2(bs, offset, nb_clusters); + if (ret < 0) { +- return ret; ++ goto fail; + } + + nb_clusters -= ret; + offset += (ret * s->cluster_size); + } + +- return 0; ++ ret = 0; ++fail: ++ s->cache_discards = false; ++ qcow2_process_discards(bs, ret); ++ ++ return ret; + } + + /* +@@ -1450,15 +1457,22 @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors) + /* Each L2 table is handled by its own loop iteration */ + nb_clusters = size_to_clusters(s, nb_sectors << BDRV_SECTOR_BITS); + ++ s->cache_discards = true; ++ + while (nb_clusters > 0) { + ret = zero_single_l2(bs, offset, nb_clusters); + if (ret < 0) { +- return ret; ++ goto fail; + } + + nb_clusters -= ret; + offset += (ret * s->cluster_size); + } + +- return 0; ++ ret = 0; ++fail: ++ s->cache_discards = false; ++ qcow2_process_discards(bs, ret); ++ ++ return ret; + } +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 7488988..1244693 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -420,6 +420,74 @@ fail_block: + return ret; + } + ++void qcow2_process_discards(BlockDriverState *bs, int ret) ++{ ++ BDRVQcowState *s = bs->opaque; ++ Qcow2DiscardRegion *d, *next; ++ ++ QTAILQ_FOREACH_SAFE(d, &s->discards, next, next) { ++ QTAILQ_REMOVE(&s->discards, d, next); ++ ++ /* Discard is optional, ignore the return value */ ++ if (ret >= 0) { ++ bdrv_discard(bs->file, ++ d->offset >> BDRV_SECTOR_BITS, ++ d->bytes >> BDRV_SECTOR_BITS); ++ } ++ ++ g_free(d); ++ } ++} ++ ++static void update_refcount_discard(BlockDriverState *bs, ++ uint64_t offset, uint64_t length) ++{ ++ BDRVQcowState *s = bs->opaque; ++ Qcow2DiscardRegion *d, *p, *next; ++ ++ QTAILQ_FOREACH(d, &s->discards, next) { ++ uint64_t new_start = MIN(offset, d->offset); ++ uint64_t new_end = MAX(offset + length, d->offset + d->bytes); ++ ++ if (new_end - new_start <= length + d->bytes) { ++ /* There can't be any overlap, areas ending up here have no ++ * references any more and therefore shouldn't get freed another ++ * time. */ ++ assert(d->bytes + length == new_end - new_start); ++ d->offset = new_start; ++ d->bytes = new_end - new_start; ++ goto found; ++ } ++ } ++ ++ d = g_malloc(sizeof(*d)); ++ *d = (Qcow2DiscardRegion) { ++ .bs = bs, ++ .offset = offset, ++ .bytes = length, ++ }; ++ QTAILQ_INSERT_TAIL(&s->discards, d, next); ++ ++found: ++ /* Merge discard requests if they are adjacent now */ ++ QTAILQ_FOREACH_SAFE(p, &s->discards, next, next) { ++ if (p == d ++ || p->offset > d->offset + d->bytes ++ || d->offset > p->offset + p->bytes) ++ { ++ continue; ++ } ++ ++ /* Still no overlap possible */ ++ assert(p->offset == d->offset + d->bytes ++ || d->offset == p->offset + p->bytes); ++ ++ QTAILQ_REMOVE(&s->discards, p, next); ++ d->offset = MIN(d->offset, p->offset); ++ d->bytes += p->bytes; ++ } ++} ++ + /* XXX: cache several refcount block clusters ? */ + static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + int64_t offset, int64_t length, int addend, enum qcow2_discard_type type) +@@ -488,15 +556,18 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + s->free_cluster_index = cluster_index; + } + refcount_block[block_index] = cpu_to_be16(refcount); ++ + if (refcount == 0 && s->discard_passthrough[type]) { +- /* Try discarding, ignore errors */ +- /* FIXME Doing this cluster by cluster will be painfully slow */ +- bdrv_discard(bs->file, cluster_offset, 1); ++ update_refcount_discard(bs, cluster_offset, s->cluster_size); + } + } + + ret = 0; + fail: ++ if (!s->cache_discards) { ++ qcow2_process_discards(bs, ret); ++ } ++ + /* Write last changed block to disk */ + if (refcount_block) { + int wret; +@@ -755,6 +826,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + l1_table = NULL; + l1_size2 = l1_size * sizeof(uint64_t); + ++ s->cache_discards = true; ++ + /* WARNING: qcow2_snapshot_goto relies on this function not using the + * l1_table_offset when it is the current s->l1_table_offset! Be careful + * when changing this! */ +@@ -867,6 +940,9 @@ fail: + qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); + } + ++ s->cache_discards = false; ++ qcow2_process_discards(bs, ret); ++ + /* Update L1 only if it isn't deleted anyway (addend = -1) */ + if (ret == 0 && addend >= 0 && l1_modified) { + for (i = 0; i < l1_size; i++) { +diff --git a/block/qcow2.c b/block/qcow2.c +index ef8a2ca..9383990 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -486,6 +486,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) + } + + QLIST_INIT(&s->cluster_allocs); ++ QTAILQ_INIT(&s->discards); + + /* read qcow2 extensions */ + if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) { +diff --git a/block/qcow2.h b/block/qcow2.h +index 6f91b9a..3b2d5cd 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -147,6 +147,13 @@ typedef struct Qcow2Feature { + char name[46]; + } QEMU_PACKED Qcow2Feature; + ++typedef struct Qcow2DiscardRegion { ++ BlockDriverState *bs; ++ uint64_t offset; ++ uint64_t bytes; ++ QTAILQ_ENTRY(Qcow2DiscardRegion) next; ++} Qcow2DiscardRegion; ++ + typedef struct BDRVQcowState { + int cluster_bits; + int cluster_size; +@@ -199,6 +206,8 @@ typedef struct BDRVQcowState { + size_t unknown_header_fields_size; + void* unknown_header_fields; + QLIST_HEAD(, Qcow2UnknownHeaderExtension) unknown_header_ext; ++ QTAILQ_HEAD (, Qcow2DiscardRegion) discards; ++ bool cache_discards; + } BDRVQcowState; + + /* XXX: use std qcow open function ? */ +@@ -374,6 +383,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs, + int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + BdrvCheckMode fix); + ++void qcow2_process_discards(BlockDriverState *bs, int ret); ++ + /* qcow2-cluster.c functions */ + int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + bool exact_size); +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-CHECK_OFLAG_COPIED-is-obsolete.patch b/SOURCES/kvm-qcow2-CHECK_OFLAG_COPIED-is-obsolete.patch new file mode 100644 index 0000000..119af88 --- /dev/null +++ b/SOURCES/kvm-qcow2-CHECK_OFLAG_COPIED-is-obsolete.patch @@ -0,0 +1,62 @@ +From 7cc09be75f219d045f060ffd60e6c29125a82a8f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:24 +0100 +Subject: [PATCH 31/87] qcow2: CHECK_OFLAG_COPIED is obsolete + +RH-Author: Max Reitz +Message-id: <1383604354-12743-34-git-send-email-mreitz@redhat.com> +Patchwork-id: 55333 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 33/43] qcow2: CHECK_OFLAG_COPIED is obsolete +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +CHECK_OFLAG_COPIED as a parameter to check_refcounts_l1 and +check_refcounts_l2 is obselete now, since the OFLAG_COPIED consistency +check is actually no longer performed by these functions (but by +check_oflag_copied). + +Signed-off-by: Max Reitz +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit db0749012b3d1cf655bddb3cc79052a0fd4dc97b) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 4 +--- + 1 files changed, 1 insertions(+), 3 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 927bdeb..2a589b8 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1016,7 +1016,6 @@ static void inc_refcounts(BlockDriverState *bs, + + /* Flags for check_refcounts_l1() and check_refcounts_l2() */ + enum { +- CHECK_OFLAG_COPIED = 0x1, /* check QCOW_OFLAG_COPIED matches refcount */ + CHECK_FRAG_INFO = 0x2, /* update BlockFragInfo counters */ + }; + +@@ -1463,8 +1462,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + + /* current L1 table */ + ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters, +- s->l1_table_offset, s->l1_size, +- CHECK_OFLAG_COPIED | CHECK_FRAG_INFO); ++ s->l1_table_offset, s->l1_size, CHECK_FRAG_INFO); + if (ret < 0) { + goto fail; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Correct-endianness-in-overlap-check.patch b/SOURCES/kvm-qcow2-Correct-endianness-in-overlap-check.patch new file mode 100644 index 0000000..63de5b0 --- /dev/null +++ b/SOURCES/kvm-qcow2-Correct-endianness-in-overlap-check.patch @@ -0,0 +1,53 @@ +From 2ded69dfa67b8243d579e26839db43a288c251b8 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:25 +0100 +Subject: [PATCH 32/87] qcow2: Correct endianness in overlap check + +RH-Author: Max Reitz +Message-id: <1383604354-12743-35-git-send-email-mreitz@redhat.com> +Patchwork-id: 55334 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 34/43] qcow2: Correct endianness in overlap check +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +If an inactive L1 table is loaded from disk, its entries are in big +endian and have to be converted to host byte order before using them. + +Signed-off-by: Max Reitz +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 1e242b5544a48bc43eca9c637dc91ec06bcf3a31) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 2a589b8..34fcf2f 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1713,8 +1713,8 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, + } + + for (j = 0; j < l1_sz; j++) { +- if ((l1[j] & L1E_OFFSET_MASK) && +- overlaps_with(l1[j] & L1E_OFFSET_MASK, s->cluster_size)) { ++ uint64_t l2_ofs = be64_to_cpu(l1[j]) & L1E_OFFSET_MASK; ++ if (l2_ofs && overlaps_with(l2_ofs, s->cluster_size)) { + g_free(l1); + return QCOW2_OL_INACTIVE_L2; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Correct-snapshots-size-for-overlap-check.patch b/SOURCES/kvm-qcow2-Correct-snapshots-size-for-overlap-check.patch new file mode 100644 index 0000000..d49414a --- /dev/null +++ b/SOURCES/kvm-qcow2-Correct-snapshots-size-for-overlap-check.patch @@ -0,0 +1,58 @@ +From f9b42568a13151521cb8edf38f567e8c5cf25396 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:23 +0100 +Subject: [PATCH 30/87] qcow2: Correct snapshots size for overlap check + +RH-Author: Max Reitz +Message-id: <1383604354-12743-33-git-send-email-mreitz@redhat.com> +Patchwork-id: 55332 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 32/43] qcow2: Correct snapshots size for overlap check +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Using s->snapshots_size instead of snapshots_size for the metadata +overlap check in qcow2_write_snapshots leads to the detection of an +overlap with the main qcow2 image header when deleting the last +snapshot, since s->snapshots_size has not yet been updated and is +therefore non-zero. However, the offset returned by qcow2_alloc_clusters +will be zero since snapshots_size is zero. Therefore, an overlap is +detected albeit no such will occur. + +This patch fixes this by replacing s->snapshots_size by snapshots_size +when calling qcow2_pre_write_overlap_check. + +Signed-off-by: Max Reitz +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 0f39ac9a07cc10278e37d87076b143008f28aa3b) + +Signed-off-by: Max Reitz +--- + block/qcow2-snapshot.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-snapshot.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index e7e6013..450e4f5 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -192,7 +192,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs) + /* The snapshot list position has not yet been updated, so these clusters + * must indeed be completely free */ + ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset, +- s->snapshots_size); ++ snapshots_size); + if (ret < 0) { + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Employ-metadata-overlap-checks.patch b/SOURCES/kvm-qcow2-Employ-metadata-overlap-checks.patch new file mode 100644 index 0000000..850276d --- /dev/null +++ b/SOURCES/kvm-qcow2-Employ-metadata-overlap-checks.patch @@ -0,0 +1,229 @@ +From b4dbb84eeca1c793c08b39fe26f3772f200eff36 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:01 +0100 +Subject: [PATCH 08/87] qcow2: Employ metadata overlap checks + +RH-Author: Max Reitz +Message-id: <1383604354-12743-11-git-send-email-mreitz@redhat.com> +Patchwork-id: 55310 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 10/43] qcow2: Employ metadata overlap checks +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +The pre-write overlap check function is now called before most of the +qcow2 writes (aborting it on collision or other error). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit cf93980e775b709ec8f33f55846e6dcf1c7a612c) + +Signed-off-by: Max Reitz +--- + block/qcow2-cache.c | 17 +++++++++++++++++ + block/qcow2-cluster.c | 21 +++++++++++++++++++++ + block/qcow2-snapshot.c | 22 ++++++++++++++++++++++ + block/qcow2.c | 26 ++++++++++++++++++++++++++ + 4 files changed, 86 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cache.c | 17 +++++++++++++++++ + block/qcow2-cluster.c | 21 +++++++++++++++++++++ + block/qcow2-snapshot.c | 22 ++++++++++++++++++++++ + block/qcow2.c | 26 ++++++++++++++++++++++++++ + 4 files changed, 86 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c +index 2f3114e..7bcae09 100644 +--- a/block/qcow2-cache.c ++++ b/block/qcow2-cache.c +@@ -115,6 +115,23 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) + } + + if (c == s->refcount_block_cache) { ++ ret = qcow2_pre_write_overlap_check(bs, ++ QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_BLOCK, ++ c->entries[i].offset, s->cluster_size); ++ } else if (c == s->l2_table_cache) { ++ ret = qcow2_pre_write_overlap_check(bs, ++ QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, ++ c->entries[i].offset, s->cluster_size); ++ } else { ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ c->entries[i].offset, s->cluster_size); ++ } ++ ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (c == s->refcount_block_cache) { + BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART); + } else if (c == s->l2_table_cache) { + BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE); +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index cca76d4..7c248aa 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -80,6 +80,14 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + goto fail; + } + ++ /* the L1 position has not yet been updated, so these clusters must ++ * indeed be completely free */ ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ new_l1_table_offset, new_l1_size2); ++ if (ret < 0) { ++ goto fail; ++ } ++ + BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE); + for(i = 0; i < s->l1_size; i++) + new_l1_table[i] = cpu_to_be64(new_l1_table[i]); +@@ -149,6 +157,13 @@ static int write_l1_entry(BlockDriverState *bs, int l1_index) + buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); + } + ++ ret = qcow2_pre_write_overlap_check(bs, ++ QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1, ++ s->l1_table_offset + 8 * l1_start_index, sizeof(buf)); ++ if (ret < 0) { ++ return ret; ++ } ++ + BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE); + ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset + 8 * l1_start_index, + buf, sizeof(buf)); +@@ -368,6 +383,12 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs, + &s->aes_encrypt_key); + } + ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE); ++ if (ret < 0) { ++ goto out; ++ } ++ + BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE); + ret = bdrv_co_writev(bs->file, (cluster_offset >> 9) + n_start, n, &qiov); + if (ret < 0) { +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index 0caac90..e7e6013 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -189,6 +189,15 @@ static int qcow2_write_snapshots(BlockDriverState *bs) + return ret; + } + ++ /* The snapshot list position has not yet been updated, so these clusters ++ * must indeed be completely free */ ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset, ++ s->snapshots_size); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ + /* Write all snapshots to the new list */ + for(i = 0; i < s->nb_snapshots; i++) { + sn = s->snapshots + i; +@@ -363,6 +372,12 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) + l1_table[i] = cpu_to_be64(s->l1_table[i]); + } + ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ sn->l1_table_offset, s->l1_size * sizeof(uint64_t)); ++ if (ret < 0) { ++ goto fail; ++ } ++ + ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table, + s->l1_size * sizeof(uint64_t)); + if (ret < 0) { +@@ -475,6 +490,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) + goto fail; + } + ++ ret = qcow2_pre_write_overlap_check(bs, ++ QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1, ++ s->l1_table_offset, cur_l1_bytes); ++ if (ret < 0) { ++ goto fail; ++ } ++ + ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table, + cur_l1_bytes); + if (ret < 0) { +diff --git a/block/qcow2.c b/block/qcow2.c +index aa9dd23..90950cb 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -624,6 +624,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) + qcow2_free_snapshots(bs); + qcow2_refcount_close(bs); + g_free(s->l1_table); ++ /* else pre-write overlap checks in cache_destroy may crash */ ++ s->l1_table = NULL; + if (s->l2_table_cache) { + qcow2_cache_destroy(bs, s->l2_table_cache); + } +@@ -933,6 +935,13 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, + cur_nr_sectors * 512); + } + ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE, ++ cur_nr_sectors * BDRV_SECTOR_SIZE); ++ if (ret < 0) { ++ goto fail; ++ } ++ + qemu_co_mutex_unlock(&s->lock); + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); + trace_qcow2_writev_data(qemu_coroutine_self(), +@@ -999,6 +1008,8 @@ static void qcow2_close(BlockDriverState *bs) + { + BDRVQcowState *s = bs->opaque; + g_free(s->l1_table); ++ /* else pre-write overlap checks in cache_destroy may crash */ ++ s->l1_table = NULL; + + qcow2_cache_flush(bs, s->l2_table_cache); + qcow2_cache_flush(bs, s->refcount_block_cache); +@@ -1676,6 +1687,14 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, + + if (ret != Z_STREAM_END || out_len >= s->cluster_size) { + /* could not compress: write normal cluster */ ++ ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ sector_num * BDRV_SECTOR_SIZE, ++ s->cluster_sectors * BDRV_SECTOR_SIZE); ++ if (ret < 0) { ++ goto fail; ++ } ++ + ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors); + if (ret < 0) { + goto fail; +@@ -1688,6 +1707,13 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, + goto fail; + } + cluster_offset &= s->cluster_offset_mask; ++ ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ cluster_offset, out_len); ++ if (ret < 0) { ++ goto fail; ++ } ++ + BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED); + ret = bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len); + if (ret < 0) { +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Evaluate-overlap-check-options.patch b/SOURCES/kvm-qcow2-Evaluate-overlap-check-options.patch new file mode 100644 index 0000000..ebe3fac --- /dev/null +++ b/SOURCES/kvm-qcow2-Evaluate-overlap-check-options.patch @@ -0,0 +1,84 @@ +From c5321890678045bf4de3b1845110aeed348203b9 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:34 +0100 +Subject: [PATCH 41/87] qcow2: Evaluate overlap check options + +RH-Author: Max Reitz +Message-id: <1383604354-12743-44-git-send-email-mreitz@redhat.com> +Patchwork-id: 55343 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 43/43] qcow2: Evaluate overlap check options +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Evaluate the runtime overlap check options and set +BDRVQcowState.overlap_check appropriately. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 1fa5cc839aa6068c9182ad8d611f844c58f95f42) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 29 ++++++++++++++++++++++++++++- + 1 files changed, 28 insertions(+), 1 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index b6f300d..01b535d 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -425,6 +425,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + Error *local_err = NULL; + uint64_t ext_end; + uint64_t l1_vm_state_index; ++ const char *opt_overlap_check; ++ int overlap_check_template = 0; + + ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); + if (ret < 0) { +@@ -687,7 +689,32 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + s->discard_passthrough[QCOW2_DISCARD_OTHER] = + qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); + +- s->overlap_check = QCOW2_OL_CACHED; ++ opt_overlap_check = qemu_opt_get(opts, "overlap-check") ?: "cached"; ++ if (!strcmp(opt_overlap_check, "none")) { ++ overlap_check_template = 0; ++ } else if (!strcmp(opt_overlap_check, "constant")) { ++ overlap_check_template = QCOW2_OL_CONSTANT; ++ } else if (!strcmp(opt_overlap_check, "cached")) { ++ overlap_check_template = QCOW2_OL_CACHED; ++ } else if (!strcmp(opt_overlap_check, "all")) { ++ overlap_check_template = QCOW2_OL_ALL; ++ } else { ++ error_setg(errp, "Unsupported value '%s' for qcow2 option " ++ "'overlap-check'. Allowed are either of the following: " ++ "none, constant, cached, all", opt_overlap_check); ++ qemu_opts_del(opts); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ s->overlap_check = 0; ++ for (i = 0; i < QCOW2_OL_MAX_BITNR; i++) { ++ /* overlap-check defines a template bitmask, but every flag may be ++ * overwritten through the associated boolean option */ ++ s->overlap_check |= ++ qemu_opt_get_bool(opts, overlap_bool_option_names[i], ++ overlap_check_template & (1 << i)) << i; ++ } + + qemu_opts_del(opts); + +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Make-overlap-check-mask-variable.patch b/SOURCES/kvm-qcow2-Make-overlap-check-mask-variable.patch new file mode 100644 index 0000000..a17503f --- /dev/null +++ b/SOURCES/kvm-qcow2-Make-overlap-check-mask-variable.patch @@ -0,0 +1,90 @@ +From 0d32273cd7f5daa7431b5e2068537154dea101fb Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:30 +0100 +Subject: [PATCH 37/87] qcow2: Make overlap check mask variable + +RH-Author: Max Reitz +Message-id: <1383604354-12743-40-git-send-email-mreitz@redhat.com> +Patchwork-id: 55339 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 39/43] qcow2: Make overlap check mask variable +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Replace the QCOW2_OL_DEFAULT macro by a variable overlap_check in +BDRVQcowState. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 3e3553905cfc814d59de6d1a634c3a991b2a9257) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 2 +- + block/qcow2.c | 2 ++ + block/qcow2.h | 5 ++--- + 3 files changed, 5 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 2 +- + block/qcow2.c | 2 ++ + block/qcow2.h | 5 ++--- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 91c446b..3787314 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1629,7 +1629,7 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, + int64_t size) + { + BDRVQcowState *s = bs->opaque; +- int chk = QCOW2_OL_DEFAULT & ~ign; ++ int chk = s->overlap_check & ~ign; + int i, j; + + if (!size) { +diff --git a/block/qcow2.c b/block/qcow2.c +index ac5ed47..157361f 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -630,6 +630,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + s->discard_passthrough[QCOW2_DISCARD_OTHER] = + qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); + ++ s->overlap_check = QCOW2_OL_CACHED; ++ + qemu_opts_del(opts); + + if (s->use_lazy_refcounts && s->qcow_version < 3) { +diff --git a/block/qcow2.h b/block/qcow2.h +index 64ad43c..d1fd91b 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -202,6 +202,8 @@ typedef struct BDRVQcowState { + + bool discard_passthrough[QCOW2_DISCARD_MAX]; + ++ int overlap_check; /* bitmask of Qcow2MetadataOverlap values */ ++ + uint64_t incompatible_features; + uint64_t compatible_features; + uint64_t autoclear_features; +@@ -320,9 +322,6 @@ typedef enum QCow2MetadataOverlap { + QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \ + QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1) + +-/* The default checks to perform */ +-#define QCOW2_OL_DEFAULT QCOW2_OL_CACHED +- + #define L1E_OFFSET_MASK 0x00ffffffffffff00ULL + #define L2E_OFFSET_MASK 0x00ffffffffffff00ULL + #define L2E_COMPRESSED_OFFSET_SIZE_MASK 0x3fffffffffffffffULL +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Metadata-overlap-checks.patch b/SOURCES/kvm-qcow2-Metadata-overlap-checks.patch new file mode 100644 index 0000000..578491e --- /dev/null +++ b/SOURCES/kvm-qcow2-Metadata-overlap-checks.patch @@ -0,0 +1,321 @@ +From 4413b8524dfa9dc3a6a494a2cf031265d6ef16f3 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:00 +0100 +Subject: [PATCH 07/87] qcow2: Metadata overlap checks + +RH-Author: Max Reitz +Message-id: <1383604354-12743-10-git-send-email-mreitz@redhat.com> +Patchwork-id: 55309 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 09/43] qcow2: Metadata overlap checks +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Two new functions are added; the first one checks a given range in the +image file for overlaps with metadata (main header, L1 tables, L2 +tables, refcount table and blocks). + +The second one should be used immediately before writing to the image +file as it calls the first function and, upon collision, marks the +image as corrupt and makes the BDS unusable, thereby preventing +further access. + +Both functions take a bitmask argument specifying the structures which +should be checked for overlaps, making it possible to also check +metadata writes against colliding with other structures. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit a40f1c2add4d5f58d594f810fe36cabcf32bc4b0) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 39 +++++++++++ + include/monitor/monitor.h | 1 + + monitor.c | 1 + + 4 files changed, 213 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 172 +++++++++++++++++++++++++++++++++++++++++++++ + block/qcow2.h | 39 ++++++++++ + include/monitor/monitor.h | 1 + + monitor.c | 1 + + 4 files changed, 213 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 1244693..310efcc 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -25,6 +25,8 @@ + #include "qemu-common.h" + #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, int64_t size); + static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, +@@ -1372,3 +1374,173 @@ fail: + return ret; + } + ++#define overlaps_with(ofs, sz) \ ++ ranges_overlap(offset, size, ofs, sz) ++ ++/* ++ * Checks if the given offset into the image file is actually free to use by ++ * looking for overlaps with important metadata sections (L1/L2 tables etc.), ++ * i.e. a sanity check without relying on the refcount tables. ++ * ++ * The chk parameter specifies exactly what checks to perform (being a bitmask ++ * of QCow2MetadataOverlap values). ++ * ++ * Returns: ++ * - 0 if writing to this offset will not affect the mentioned metadata ++ * - a positive QCow2MetadataOverlap value indicating one overlapping section ++ * - a negative value (-errno) indicating an error while performing a check, ++ * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2 ++ */ ++int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, ++ int64_t size) ++{ ++ BDRVQcowState *s = bs->opaque; ++ int i, j; ++ ++ if (!size) { ++ return 0; ++ } ++ ++ if (chk & QCOW2_OL_MAIN_HEADER) { ++ if (offset < s->cluster_size) { ++ return QCOW2_OL_MAIN_HEADER; ++ } ++ } ++ ++ /* align range to test to cluster boundaries */ ++ size = align_offset(offset_into_cluster(s, offset) + size, s->cluster_size); ++ offset = start_of_cluster(s, offset); ++ ++ if ((chk & QCOW2_OL_ACTIVE_L1) && s->l1_size) { ++ if (overlaps_with(s->l1_table_offset, s->l1_size * sizeof(uint64_t))) { ++ return QCOW2_OL_ACTIVE_L1; ++ } ++ } ++ ++ if ((chk & QCOW2_OL_REFCOUNT_TABLE) && s->refcount_table_size) { ++ if (overlaps_with(s->refcount_table_offset, ++ s->refcount_table_size * sizeof(uint64_t))) { ++ return QCOW2_OL_REFCOUNT_TABLE; ++ } ++ } ++ ++ if ((chk & QCOW2_OL_SNAPSHOT_TABLE) && s->snapshots_size) { ++ if (overlaps_with(s->snapshots_offset, s->snapshots_size)) { ++ return QCOW2_OL_SNAPSHOT_TABLE; ++ } ++ } ++ ++ if ((chk & QCOW2_OL_INACTIVE_L1) && s->snapshots) { ++ for (i = 0; i < s->nb_snapshots; i++) { ++ if (s->snapshots[i].l1_size && ++ overlaps_with(s->snapshots[i].l1_table_offset, ++ s->snapshots[i].l1_size * sizeof(uint64_t))) { ++ return QCOW2_OL_INACTIVE_L1; ++ } ++ } ++ } ++ ++ if ((chk & QCOW2_OL_ACTIVE_L2) && s->l1_table) { ++ for (i = 0; i < s->l1_size; i++) { ++ if ((s->l1_table[i] & L1E_OFFSET_MASK) && ++ overlaps_with(s->l1_table[i] & L1E_OFFSET_MASK, ++ s->cluster_size)) { ++ return QCOW2_OL_ACTIVE_L2; ++ } ++ } ++ } ++ ++ if ((chk & QCOW2_OL_REFCOUNT_BLOCK) && s->refcount_table) { ++ for (i = 0; i < s->refcount_table_size; i++) { ++ if ((s->refcount_table[i] & REFT_OFFSET_MASK) && ++ overlaps_with(s->refcount_table[i] & REFT_OFFSET_MASK, ++ s->cluster_size)) { ++ return QCOW2_OL_REFCOUNT_BLOCK; ++ } ++ } ++ } ++ ++ if ((chk & QCOW2_OL_INACTIVE_L2) && s->snapshots) { ++ for (i = 0; i < s->nb_snapshots; i++) { ++ uint64_t l1_ofs = s->snapshots[i].l1_table_offset; ++ uint32_t l1_sz = s->snapshots[i].l1_size; ++ uint64_t *l1 = g_malloc(l1_sz * sizeof(uint64_t)); ++ int ret; ++ ++ ret = bdrv_read(bs->file, l1_ofs / BDRV_SECTOR_SIZE, (uint8_t *)l1, ++ l1_sz * sizeof(uint64_t) / BDRV_SECTOR_SIZE); ++ ++ if (ret < 0) { ++ g_free(l1); ++ return ret; ++ } ++ ++ for (j = 0; j < l1_sz; j++) { ++ if ((l1[j] & L1E_OFFSET_MASK) && ++ overlaps_with(l1[j] & L1E_OFFSET_MASK, s->cluster_size)) { ++ g_free(l1); ++ return QCOW2_OL_INACTIVE_L2; ++ } ++ } ++ ++ g_free(l1); ++ } ++ } ++ ++ return 0; ++} ++ ++static const char *metadata_ol_names[] = { ++ [QCOW2_OL_MAIN_HEADER_BITNR] = "qcow2_header", ++ [QCOW2_OL_ACTIVE_L1_BITNR] = "active L1 table", ++ [QCOW2_OL_ACTIVE_L2_BITNR] = "active L2 table", ++ [QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table", ++ [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block", ++ [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table", ++ [QCOW2_OL_INACTIVE_L1_BITNR] = "inactive L1 table", ++ [QCOW2_OL_INACTIVE_L2_BITNR] = "inactive L2 table", ++}; ++ ++/* ++ * First performs a check for metadata overlaps (through ++ * qcow2_check_metadata_overlap); if that fails with a negative value (error ++ * while performing a check), that value is returned. If an impending overlap ++ * is detected, the BDS will be made unusable, the qcow2 file marked corrupt ++ * and -EIO returned. ++ * ++ * Returns 0 if there were neither overlaps nor errors while checking for ++ * overlaps; or a negative value (-errno) on error. ++ */ ++int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset, ++ int64_t size) ++{ ++ int ret = qcow2_check_metadata_overlap(bs, chk, offset, size); ++ ++ if (ret < 0) { ++ 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 " }", 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 */ ++ return -EIO; ++ } ++ ++ return 0; ++} +diff --git a/block/qcow2.h b/block/qcow2.h +index 4297487..86ddb30 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -289,6 +289,40 @@ enum { + QCOW2_CLUSTER_ZERO + }; + ++typedef enum QCow2MetadataOverlap { ++ QCOW2_OL_MAIN_HEADER_BITNR = 0, ++ QCOW2_OL_ACTIVE_L1_BITNR = 1, ++ QCOW2_OL_ACTIVE_L2_BITNR = 2, ++ QCOW2_OL_REFCOUNT_TABLE_BITNR = 3, ++ QCOW2_OL_REFCOUNT_BLOCK_BITNR = 4, ++ QCOW2_OL_SNAPSHOT_TABLE_BITNR = 5, ++ QCOW2_OL_INACTIVE_L1_BITNR = 6, ++ QCOW2_OL_INACTIVE_L2_BITNR = 7, ++ ++ QCOW2_OL_MAX_BITNR = 8, ++ ++ QCOW2_OL_NONE = 0, ++ QCOW2_OL_MAIN_HEADER = (1 << QCOW2_OL_MAIN_HEADER_BITNR), ++ QCOW2_OL_ACTIVE_L1 = (1 << QCOW2_OL_ACTIVE_L1_BITNR), ++ QCOW2_OL_ACTIVE_L2 = (1 << QCOW2_OL_ACTIVE_L2_BITNR), ++ QCOW2_OL_REFCOUNT_TABLE = (1 << QCOW2_OL_REFCOUNT_TABLE_BITNR), ++ QCOW2_OL_REFCOUNT_BLOCK = (1 << QCOW2_OL_REFCOUNT_BLOCK_BITNR), ++ QCOW2_OL_SNAPSHOT_TABLE = (1 << QCOW2_OL_SNAPSHOT_TABLE_BITNR), ++ QCOW2_OL_INACTIVE_L1 = (1 << QCOW2_OL_INACTIVE_L1_BITNR), ++ /* NOTE: Checking overlaps with inactive L2 tables will result in bdrv ++ * reads. */ ++ QCOW2_OL_INACTIVE_L2 = (1 << QCOW2_OL_INACTIVE_L2_BITNR), ++} QCow2MetadataOverlap; ++ ++/* Perform all overlap checks which don't require disk access */ ++#define QCOW2_OL_CACHED \ ++ (QCOW2_OL_MAIN_HEADER | QCOW2_OL_ACTIVE_L1 | QCOW2_OL_ACTIVE_L2 | \ ++ QCOW2_OL_REFCOUNT_TABLE | QCOW2_OL_REFCOUNT_BLOCK | \ ++ QCOW2_OL_SNAPSHOT_TABLE | QCOW2_OL_INACTIVE_L1) ++ ++/* The default checks to perform */ ++#define QCOW2_OL_DEFAULT QCOW2_OL_CACHED ++ + #define L1E_OFFSET_MASK 0x00ffffffffffff00ULL + #define L2E_OFFSET_MASK 0x00ffffffffffff00ULL + #define L2E_COMPRESSED_OFFSET_SIZE_MASK 0x3fffffffffffffffULL +@@ -390,6 +424,11 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + + void qcow2_process_discards(BlockDriverState *bs, int ret); + ++int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, ++ int64_t size); ++int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset, ++ int64_t size); ++ + /* qcow2-cluster.c functions */ + int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + bool exact_size); +diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h +index 1a6cfcf..07b41a6 100644 +--- a/include/monitor/monitor.h ++++ b/include/monitor/monitor.h +@@ -47,6 +47,7 @@ typedef enum MonitorEvent { + QEVENT_BALLOON_CHANGE, + QEVENT_SPICE_MIGRATE_COMPLETED, + QEVENT_GUEST_PANICKED, ++ QEVENT_BLOCK_IMAGE_CORRUPTED, + + /* Add to 'monitor_event_names' array in monitor.c when + * defining new events here */ +diff --git a/monitor.c b/monitor.c +index deb0dc8..c226acf 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -504,6 +504,7 @@ static const char *monitor_event_names[] = { + [QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE", + [QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED", + [QEVENT_GUEST_PANICKED] = "GUEST_PANICKED", ++ [QEVENT_BLOCK_IMAGE_CORRUPTED] = "BLOCK_IMAGE_CORRUPTED", + }; + QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX) + +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Options-to-enable-discard-for-freed-clusters.patch b/SOURCES/kvm-qcow2-Options-to-enable-discard-for-freed-clusters.patch new file mode 100644 index 0000000..f796ff0 --- /dev/null +++ b/SOURCES/kvm-qcow2-Options-to-enable-discard-for-freed-clusters.patch @@ -0,0 +1,124 @@ +From 789d0334d894eaea6a5ca35538926bbb63a9cea3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Mon, 9 Sep 2013 14:28:01 +0200 +Subject: [PATCH 10/38] qcow2: Options to enable discard for freed clusters + +RH-Author: Kevin Wolf +Message-id: <1378736903-18489-11-git-send-email-kwolf@redhat.com> +Patchwork-id: 54195 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 10/32] qcow2: Options to enable discard for freed clusters +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +Deleted snapshots are discarded in the image file by default, discard +requests take their default from the -drive discard=... option and other +places that free clusters must always be enabled explicitly. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 67af674e478054086f972811dd0a11289afa39a9) + +Signed-off-by: Kevin Wolf +--- + block/qcow2-refcount.c | 5 +++++ + block/qcow2.c | 26 ++++++++++++++++++++++++++ + block/qcow2.h | 5 +++++ + 3 files changed, 36 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 5 +++++ + block/qcow2.c | 26 ++++++++++++++++++++++++++ + block/qcow2.h | 5 +++++ + 3 files changed, 36 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 6d35e49..7488988 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -488,6 +488,11 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs, + s->free_cluster_index = cluster_index; + } + refcount_block[block_index] = cpu_to_be16(refcount); ++ if (refcount == 0 && s->discard_passthrough[type]) { ++ /* Try discarding, ignore errors */ ++ /* FIXME Doing this cluster by cluster will be painfully slow */ ++ bdrv_discard(bs->file, cluster_offset, 1); ++ } + } + + ret = 0; +diff --git a/block/qcow2.c b/block/qcow2.c +index e28ea47..ef8a2ca 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -295,6 +295,22 @@ static QemuOptsList qcow2_runtime_opts = { + .type = QEMU_OPT_BOOL, + .help = "Postpone refcount updates", + }, ++ { ++ .name = QCOW2_OPT_DISCARD_REQUEST, ++ .type = QEMU_OPT_BOOL, ++ .help = "Pass guest discard requests to the layer below", ++ }, ++ { ++ .name = QCOW2_OPT_DISCARD_SNAPSHOT, ++ .type = QEMU_OPT_BOOL, ++ .help = "Generate discard requests when snapshot related space " ++ "is freed", ++ }, ++ { ++ .name = QCOW2_OPT_DISCARD_OTHER, ++ .type = QEMU_OPT_BOOL, ++ .help = "Generate discard requests when other clusters are freed", ++ }, + { /* end of list */ } + }, + }; +@@ -532,6 +548,16 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags) + s->use_lazy_refcounts = qemu_opt_get_bool(opts, QCOW2_OPT_LAZY_REFCOUNTS, + (s->compatible_features & QCOW2_COMPAT_LAZY_REFCOUNTS)); + ++ s->discard_passthrough[QCOW2_DISCARD_NEVER] = false; ++ s->discard_passthrough[QCOW2_DISCARD_ALWAYS] = true; ++ s->discard_passthrough[QCOW2_DISCARD_REQUEST] = ++ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_REQUEST, ++ flags & BDRV_O_UNMAP); ++ s->discard_passthrough[QCOW2_DISCARD_SNAPSHOT] = ++ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_SNAPSHOT, true); ++ s->discard_passthrough[QCOW2_DISCARD_OTHER] = ++ qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false); ++ + qemu_opts_del(opts); + + if (s->use_lazy_refcounts && s->qcow_version < 3) { +diff --git a/block/qcow2.h b/block/qcow2.h +index 64a6479..6f91b9a 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -60,6 +60,9 @@ + + + #define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts" ++#define QCOW2_OPT_DISCARD_REQUEST "pass_discard_request" ++#define QCOW2_OPT_DISCARD_SNAPSHOT "pass_discard_snapshot" ++#define QCOW2_OPT_DISCARD_OTHER "pass_discard_other" + + typedef struct QCowHeader { + uint32_t magic; +@@ -187,6 +190,8 @@ typedef struct BDRVQcowState { + int qcow_version; + bool use_lazy_refcounts; + ++ bool discard_passthrough[QCOW2_DISCARD_MAX]; ++ + uint64_t incompatible_features; + uint64_t compatible_features; + uint64_t autoclear_features; +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Remove-wrong-metadata-overlap-check.patch b/SOURCES/kvm-qcow2-Remove-wrong-metadata-overlap-check.patch new file mode 100644 index 0000000..efb0a92 --- /dev/null +++ b/SOURCES/kvm-qcow2-Remove-wrong-metadata-overlap-check.patch @@ -0,0 +1,58 @@ +From 4e3d25779bb06d9c7a39e9e36b1be8737b459e32 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:28 +0100 +Subject: [PATCH 35/87] qcow2: Remove wrong metadata overlap check + +RH-Author: Max Reitz +Message-id: <1383604354-12743-38-git-send-email-mreitz@redhat.com> +Patchwork-id: 55337 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 37/43] qcow2: Remove wrong metadata overlap check +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +In qcow2_write_compressed, if the compression fails, a normal cluster is +written to disk. This is done through bdrv_write on the qcow2 BDS +itself (using the guest offset), thus it is wrong to do a metadata +overlap check before. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit f9bff971436b5924ca3c3203c6a3dcd6437bd430) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 8 -------- + 1 file changed, 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 8 -------- + 1 files changed, 0 insertions(+), 8 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 880d2cf..8b73518 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1735,14 +1735,6 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, + + if (ret != Z_STREAM_END || out_len >= s->cluster_size) { + /* could not compress: write normal cluster */ +- +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +- sector_num * BDRV_SECTOR_SIZE, +- s->cluster_sectors * BDRV_SECTOR_SIZE); +- if (ret < 0) { +- goto fail; +- } +- + ret = bdrv_write(bs, sector_num, buf, s->cluster_sectors); + if (ret < 0) { + goto fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Restore-total_sectors-value-in-save_vmstate.patch b/SOURCES/kvm-qcow2-Restore-total_sectors-value-in-save_vmstate.patch new file mode 100644 index 0000000..9c4e39d --- /dev/null +++ b/SOURCES/kvm-qcow2-Restore-total_sectors-value-in-save_vmstate.patch @@ -0,0 +1,69 @@ +From f03758aa88454cd2efe72b7623b855331c5ee22c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2013 14:23:15 +0100 +Subject: [PATCH 27/81] qcow2: Restore total_sectors value in save_vmstate + +RH-Author: Max Reitz +Message-id: <1383315797-30938-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 55216 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 1/3] qcow2: Restore total_sectors value in save_vmstate +Bugzilla: 1025740 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Alex Williamson + +BZ: 1025740 + +Since df2a6f29a5, bdrv_co_do_writev increases the total_sectors value of +a growable block devices on writes after the current end. This leads to +the virtual disk apparently growing in qcow2_save_vmstate, which in turn +affects the disk size captured by the internal snapshot taken directly +afterwards through e.g. the HMP savevm command. Such a "grown" snapshot +cannot be loaded after reopening the qcow2 image, since its disk size +differs from the actual virtual disk size (writing a VM state does not +actually increase the virtual disk size). + +Fix this by restoring total_sectors at the end of qcow2_save_vmstate. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit eedff66f21e542650d895801549ce05ac108278b) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 8e894b9..f4adf35 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1716,6 +1716,7 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, + int64_t pos) + { + BDRVQcowState *s = bs->opaque; ++ int64_t total_sectors = bs->total_sectors; + int growable = bs->growable; + int ret; + +@@ -1724,6 +1725,11 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, + ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov); + bs->growable = growable; + ++ /* bdrv_co_do_writev will have increased the total_sectors value to include ++ * the VM state - the VM state is however not an actual part of the block ++ * device, therefore, we need to restore the old value. */ ++ bs->total_sectors = total_sectors; ++ + return ret; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Switch-L1-table-in-a-single-sequence.patch b/SOURCES/kvm-qcow2-Switch-L1-table-in-a-single-sequence.patch new file mode 100644 index 0000000..31c87db --- /dev/null +++ b/SOURCES/kvm-qcow2-Switch-L1-table-in-a-single-sequence.patch @@ -0,0 +1,72 @@ +From 45958d24d6c9bcdc333844f69f47cacec29cfa0e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:26 +0100 +Subject: [PATCH 33/87] qcow2: Switch L1 table in a single sequence + +RH-Author: Max Reitz +Message-id: <1383604354-12743-36-git-send-email-mreitz@redhat.com> +Patchwork-id: 55335 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 35/43] qcow2: Switch L1 table in a single sequence +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Switching the L1 table in memory should be an atomic operation, as far +as possible. Calling qcow2_free_clusters on the old L1 table on disk is +not a good idea when the old L1 table is no longer valid and the address +to the new one hasn't yet been written into the corresponding +BDRVQcowState field. To be more specific, this can lead to segfaults due +to qcow2_check_metadata_overlap trying to access the L1 table during the +free operation. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit fda74f826baec78d685e5a87fd8a95bfb7bb2243) + +Signed-off-by: Max Reitz +--- + block/qcow2-cluster.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 2d5aa92..c05f182 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -35,6 +35,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + BDRVQcowState *s = bs->opaque; + int new_l1_size2, ret, i; + uint64_t *new_l1_table; ++ int64_t old_l1_table_offset, old_l1_size; + int64_t new_l1_table_offset, new_l1_size; + uint8_t data[12]; + +@@ -106,11 +107,13 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + goto fail; + } + g_free(s->l1_table); +- qcow2_free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t), +- QCOW2_DISCARD_OTHER); ++ old_l1_table_offset = s->l1_table_offset; + s->l1_table_offset = new_l1_table_offset; + s->l1_table = new_l1_table; ++ old_l1_size = s->l1_size; + s->l1_size = new_l1_size; ++ qcow2_free_clusters(bs, old_l1_table_offset, old_l1_size * sizeof(uint64_t), ++ QCOW2_DISCARD_OTHER); + return 0; + fail: + g_free(new_l1_table); +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Unset-zero_beyond_eof-in-save_vmstate.patch b/SOURCES/kvm-qcow2-Unset-zero_beyond_eof-in-save_vmstate.patch new file mode 100644 index 0000000..544963b --- /dev/null +++ b/SOURCES/kvm-qcow2-Unset-zero_beyond_eof-in-save_vmstate.patch @@ -0,0 +1,61 @@ +From 3ab144fe22a867a0ffcce396302b62b0f2ac4c29 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2013 14:23:16 +0100 +Subject: [PATCH 28/81] qcow2: Unset zero_beyond_eof in save_vmstate + +RH-Author: Max Reitz +Message-id: <1383315797-30938-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 55217 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 2/3] qcow2: Unset zero_beyond_eof in save_vmstate +Bugzilla: 1025740 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Alex Williamson + +BZ: 1025740 + +Saving the VM state is done using bdrv_pwrite. This function may perform +a read-modify-write, which in this case results in data being read from +beyond the end of the virtual disk. Since we are actually trying to +access an area which is not a part of the virtual disk, zero_beyond_eof +has to be set to false before performing the partial write, otherwise +the VM state may become corrupted. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 6e13610aa454beba52944e8df6d93158d68ab911) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 3 +++ + 1 file changed, 3 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index f4adf35..c2728c9 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -1718,12 +1718,15 @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, + BDRVQcowState *s = bs->opaque; + int64_t total_sectors = bs->total_sectors; + int growable = bs->growable; ++ bool zero_beyond_eof = bs->zero_beyond_eof; + int ret; + + BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE); + bs->growable = 1; ++ bs->zero_beyond_eof = false; + ret = bdrv_pwritev(bs, qcow2_vm_state_offset(s) + pos, qiov); + bs->growable = growable; ++ bs->zero_beyond_eof = zero_beyond_eof; + + /* bdrv_co_do_writev will have increased the total_sectors value to include + * the VM state - the VM state is however not an actual part of the block +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Use-Error-parameter.patch b/SOURCES/kvm-qcow2-Use-Error-parameter.patch new file mode 100644 index 0000000..5436312 --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-Error-parameter.patch @@ -0,0 +1,498 @@ +From 9f0ec0582867ea7c45ac5b23bfcbd20e699a4bd4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:14 +0100 +Subject: [PATCH 21/87] qcow2: Use Error parameter + +RH-Author: Max Reitz +Message-id: <1383604354-12743-24-git-send-email-mreitz@redhat.com> +Patchwork-id: 55323 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 23/43] qcow2: Use Error parameter +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +Employ usage of the new Error ** parameter in qcow2_open, qcow2_create +and associated functions. + +Signed-off-by: Max Reitz +(cherry picked from commit 3ef6c40ad0b350e18c78135ffbdbe209cb479c1f) + +Signed-off-by: Max Reitz + +Conflicts: + block/qcow2.c + +Conflicts because 8ad1898c has not been backported ("qcow2: Change +default for new images to compat=1.1"). +--- + block/qcow2.c | 134 ++++++++++++++++++++++++++++++++++++++-------------------- + 1 file changed, 88 insertions(+), 46 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 134 +++++++++++++++++++++++++++++++++++++------------------- + 1 files changed, 88 insertions(+), 46 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 027d210..880d2cf 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -79,7 +79,8 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) + * return 0 upon success, non-0 otherwise + */ + static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, +- uint64_t end_offset, void **p_feature_table) ++ uint64_t end_offset, void **p_feature_table, ++ Error **errp) + { + BDRVQcowState *s = bs->opaque; + QCowExtension ext; +@@ -100,10 +101,10 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + printf("attempting to read extended header in offset %lu\n", offset); + #endif + +- if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) { +- fprintf(stderr, "qcow2_read_extension: ERROR: " +- "pread fail from offset %" PRIu64 "\n", +- offset); ++ ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext)); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: " ++ "pread fail from offset %" PRIu64, offset); + return 1; + } + be32_to_cpus(&ext.magic); +@@ -113,7 +114,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + printf("ext.magic = 0x%x\n", ext.magic); + #endif + if (ext.len > end_offset - offset) { +- error_report("Header extension too large"); ++ error_setg(errp, "Header extension too large"); + return -EINVAL; + } + +@@ -123,14 +124,16 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + + case QCOW2_EXT_MAGIC_BACKING_FORMAT: + if (ext.len >= sizeof(bs->backing_format)) { +- fprintf(stderr, "ERROR: ext_backing_format: len=%u too large" +- " (>=%zu)\n", +- ext.len, sizeof(bs->backing_format)); ++ error_setg(errp, "ERROR: ext_backing_format: len=%u too large" ++ " (>=%zu)", ext.len, sizeof(bs->backing_format)); + return 2; + } +- if (bdrv_pread(bs->file, offset , bs->backing_format, +- ext.len) != ext.len) ++ ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "ERROR: ext_backing_format: " ++ "Could not read format name"); + return 3; ++ } + bs->backing_format[ext.len] = '\0'; + #ifdef DEBUG_EXT + printf("Qcow2: Got format extension %s\n", bs->backing_format); +@@ -142,6 +145,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); + ret = bdrv_pread(bs->file, offset , feature_table, ext.len); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "ERROR: ext_feature_table: " ++ "Could not read table"); + return ret; + } + +@@ -161,6 +166,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, + + ret = bdrv_pread(bs->file, offset , uext->data, uext->len); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "ERROR: unknown extension: " ++ "Could not read data"); + return ret; + } + } +@@ -184,8 +191,8 @@ static void cleanup_unknown_header_ext(BlockDriverState *bs) + } + } + +-static void GCC_FMT_ATTR(2, 3) report_unsupported(BlockDriverState *bs, +- const char *fmt, ...) ++static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs, ++ Error **errp, const char *fmt, ...) + { + char msg[64]; + va_list ap; +@@ -194,17 +201,17 @@ static void GCC_FMT_ATTR(2, 3) report_unsupported(BlockDriverState *bs, + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + +- qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, +- bs->device_name, "qcow2", msg); ++ error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, bs->device_name, "qcow2", ++ msg); + } + + static void report_unsupported_feature(BlockDriverState *bs, +- Qcow2Feature *table, uint64_t mask) ++ Error **errp, Qcow2Feature *table, uint64_t mask) + { + while (table && table->name[0] != '\0') { + if (table->type == QCOW2_FEAT_TYPE_INCOMPATIBLE) { + if (mask & (1 << table->bit)) { +- report_unsupported(bs, "%.46s",table->name); ++ report_unsupported(bs, errp, "%.46s", table->name); + mask &= ~(1 << table->bit); + } + } +@@ -212,7 +219,8 @@ static void report_unsupported_feature(BlockDriverState *bs, + } + + if (mask) { +- report_unsupported(bs, "Unknown incompatible feature: %" PRIx64, mask); ++ report_unsupported(bs, errp, "Unknown incompatible feature: %" PRIx64, ++ mask); + } + } + +@@ -363,6 +371,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + ret = bdrv_pread(bs->file, 0, &header, sizeof(header)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read qcow2 header"); + goto fail; + } + be32_to_cpus(&header.magic); +@@ -380,11 +389,12 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + be32_to_cpus(&header.nb_snapshots); + + if (header.magic != QCOW_MAGIC) { ++ error_setg(errp, "Image is not in qcow2 format"); + ret = -EMEDIUMTYPE; + goto fail; + } + if (header.version < 2 || header.version > 3) { +- report_unsupported(bs, "QCOW version %d", header.version); ++ report_unsupported(bs, errp, "QCOW version %d", header.version); + ret = -ENOTSUP; + goto fail; + } +@@ -412,6 +422,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields, + s->unknown_header_fields_size); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read unknown qcow2 header " ++ "fields"); + goto fail; + } + } +@@ -430,8 +442,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { + void *feature_table = NULL; + qcow2_read_extensions(bs, header.header_length, ext_end, +- &feature_table); +- report_unsupported_feature(bs, feature_table, ++ &feature_table, NULL); ++ report_unsupported_feature(bs, errp, feature_table, + s->incompatible_features & + ~QCOW2_INCOMPAT_MASK); + ret = -ENOTSUP; +@@ -442,8 +454,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + /* Corrupt images may not be written to unless they are being repaired + */ + if ((flags & BDRV_O_RDWR) && !(flags & BDRV_O_CHECK)) { +- error_report("qcow2: Image is corrupt; cannot be opened " +- "read/write."); ++ error_setg(errp, "qcow2: Image is corrupt; cannot be opened " ++ "read/write"); + ret = -EACCES; + goto fail; + } +@@ -451,7 +463,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + /* Check support for various header values */ + if (header.refcount_order != 4) { +- report_unsupported(bs, "%d bit reference counts", ++ report_unsupported(bs, errp, "%d bit reference counts", + 1 << header.refcount_order); + ret = -ENOTSUP; + goto fail; +@@ -459,10 +471,13 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + if (header.cluster_bits < MIN_CLUSTER_BITS || + header.cluster_bits > MAX_CLUSTER_BITS) { ++ error_setg(errp, "Unsupported cluster size: 2^%i", header.cluster_bits); + ret = -EINVAL; + goto fail; + } + if (header.crypt_method > QCOW_CRYPT_AES) { ++ error_setg(errp, "Unsupported encryption method: %i", ++ header.crypt_method); + ret = -EINVAL; + goto fail; + } +@@ -491,6 +506,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + l1_vm_state_index = size_to_l1(s, header.size); + if (l1_vm_state_index > INT_MAX) { ++ error_setg(errp, "Image is too big"); + ret = -EFBIG; + goto fail; + } +@@ -499,6 +515,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + /* the L1 table must contain at least enough entries to put + header.size bytes */ + if (s->l1_size < s->l1_vm_state_index) { ++ error_setg(errp, "L1 table is too small"); + ret = -EINVAL; + goto fail; + } +@@ -509,6 +526,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, + s->l1_size * sizeof(uint64_t)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read L1 table"); + goto fail; + } + for(i = 0;i < s->l1_size; i++) { +@@ -529,6 +547,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + ret = qcow2_refcount_init(bs); + if (ret != 0) { ++ error_setg_errno(errp, -ret, "Could not initialize refcount handling"); + goto fail; + } + +@@ -536,7 +555,9 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + QTAILQ_INIT(&s->discards); + + /* read qcow2 extensions */ +- if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) { ++ if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL, ++ &local_err)) { ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -550,6 +571,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + ret = bdrv_pread(bs->file, header.backing_file_offset, + bs->backing_file, len); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read backing file name"); + goto fail; + } + bs->backing_file[len] = '\0'; +@@ -557,6 +579,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + ret = qcow2_read_snapshots(bs); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not read snapshots"); + goto fail; + } + +@@ -565,6 +588,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + s->autoclear_features = 0; + ret = qcow2_update_header(bs); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not update qcow2 header"); + goto fail; + } + } +@@ -579,6 +603,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + + ret = qcow2_check(bs, &result, BDRV_FIX_ERRORS); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not repair dirty image"); + goto fail; + } + } +@@ -587,8 +612,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + opts = qemu_opts_create_nofail(&qcow2_runtime_opts); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (error_is_set(&local_err)) { +- qerror_report_err(local_err); +- error_free(local_err); ++ error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } +@@ -609,8 +633,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, + qemu_opts_del(opts); + + if (s->use_lazy_refcounts && s->qcow_version < 3) { +- qerror_report(ERROR_CLASS_GENERIC_ERROR, "Lazy refcounts require " +- "a qcow2 image with at least qemu 1.1 compatibility level"); ++ error_setg(errp, "Lazy refcounts require a qcow2 image with at least " ++ "qemu 1.1 compatibility level"); + ret = -EINVAL; + goto fail; + } +@@ -1333,7 +1357,8 @@ static int preallocate(BlockDriverState *bs) + static int qcow2_create2(const char *filename, int64_t total_size, + const char *backing_file, const char *backing_format, + int flags, size_t cluster_size, int prealloc, +- QEMUOptionParameter *options, int version) ++ QEMUOptionParameter *options, int version, ++ Error **errp) + { + /* Calculate cluster_bits */ + int cluster_bits; +@@ -1341,9 +1366,8 @@ static int qcow2_create2(const char *filename, int64_t total_size, + if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS || + (1 << cluster_bits) != cluster_size) + { +- error_report( +- "Cluster size must be a power of two between %d and %dk", +- 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); ++ error_setg(errp, "Cluster size must be a power of two between %d and " ++ "%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10)); + return -EINVAL; + } + +@@ -1362,15 +1386,18 @@ static int qcow2_create2(const char *filename, int64_t total_size, + BlockDriverState* bs; + QCowHeader header; + uint8_t* refcount_table; ++ Error *local_err = NULL; + int ret; + +- ret = bdrv_create_file(filename, options, NULL); ++ ret = bdrv_create_file(filename, options, &local_err); + if (ret < 0) { ++ error_propagate(errp, local_err); + return ret; + } + +- ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, NULL); ++ ret = bdrv_file_open(&bs, filename, NULL, BDRV_O_RDWR, &local_err); + if (ret < 0) { ++ error_propagate(errp, local_err); + return ret; + } + +@@ -1400,6 +1427,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + + ret = bdrv_pwrite(bs, 0, &header, sizeof(header)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not write qcow2 header"); + goto out; + } + +@@ -1409,6 +1437,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + g_free(refcount_table); + + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not write refcount table"); + goto out; + } + +@@ -1422,13 +1451,16 @@ static int qcow2_create2(const char *filename, int64_t total_size, + BlockDriver* drv = bdrv_find_format("qcow2"); + assert(drv != NULL); + ret = bdrv_open(bs, filename, NULL, +- BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, NULL); ++ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv, &local_err); + if (ret < 0) { ++ error_propagate(errp, local_err); + goto out; + } + + ret = qcow2_alloc_clusters(bs, 2 * cluster_size); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not allocate clusters for qcow2 " ++ "header and refcount table"); + goto out; + + } else if (ret != 0) { +@@ -1439,6 +1471,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + /* Okay, now that we have a valid image, let's give it the right size */ + ret = bdrv_truncate(bs, total_size * BDRV_SECTOR_SIZE); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not resize image"); + goto out; + } + +@@ -1446,6 +1479,8 @@ static int qcow2_create2(const char *filename, int64_t total_size, + if (backing_file) { + ret = bdrv_change_backing_file(bs, backing_file, backing_format); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not assign backing file '%s' " ++ "with format '%s'", backing_file, backing_format); + goto out; + } + } +@@ -1457,6 +1492,7 @@ static int qcow2_create2(const char *filename, int64_t total_size, + ret = preallocate(bs); + qemu_co_mutex_unlock(&s->lock); + if (ret < 0) { ++ error_setg_errno(errp, -ret, "Could not preallocate metadata"); + goto out; + } + } +@@ -1477,6 +1513,8 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, + size_t cluster_size = DEFAULT_CLUSTER_SIZE; + int prealloc = 0; + int version = 2; ++ Error *local_err = NULL; ++ int ret; + + /* Read out options */ + while (options && options->name) { +@@ -1498,8 +1536,8 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, + } else if (!strcmp(options->value.s, "metadata")) { + prealloc = 1; + } else { +- fprintf(stderr, "Invalid preallocation mode: '%s'\n", +- options->value.s); ++ error_setg(errp, "Invalid preallocation mode: '%s'", ++ options->value.s); + return -EINVAL; + } + } else if (!strcmp(options->name, BLOCK_OPT_COMPAT_LEVEL)) { +@@ -1508,8 +1546,8 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, + } else if (!strcmp(options->value.s, "1.1")) { + version = 3; + } else { +- fprintf(stderr, "Invalid compatibility level: '%s'\n", +- options->value.s); ++ error_setg(errp, "Invalid compatibility level: '%s'", ++ options->value.s); + return -EINVAL; + } + } else if (!strcmp(options->name, BLOCK_OPT_LAZY_REFCOUNTS)) { +@@ -1519,19 +1557,23 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options, + } + + if (backing_file && prealloc) { +- fprintf(stderr, "Backing file and preallocation cannot be used at " +- "the same time\n"); ++ error_setg(errp, "Backing file and preallocation cannot be used at " ++ "the same time"); + return -EINVAL; + } + + if (version < 3 && (flags & BLOCK_FLAG_LAZY_REFCOUNTS)) { +- fprintf(stderr, "Lazy refcounts only supported with compatibility " +- "level 1.1 and above (use compat=1.1 or greater)\n"); ++ error_setg(errp, "Lazy refcounts only supported with compatibility " ++ "level 1.1 and above (use compat=1.1 or greater)"); + return -EINVAL; + } + +- return qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, +- cluster_size, prealloc, options, version); ++ ret = qcow2_create2(filename, sectors, backing_file, backing_fmt, flags, ++ cluster_size, prealloc, options, version, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ } ++ return ret; + } + + static int qcow2_make_empty(BlockDriverState *bs) +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Use-dashes-instead-of-underscores-in-options.patch b/SOURCES/kvm-qcow2-Use-dashes-instead-of-underscores-in-options.patch new file mode 100644 index 0000000..d169a7d --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-dashes-instead-of-underscores-in-options.patch @@ -0,0 +1,152 @@ +From c8fa26b697c9ca4fc90909e9c93471ea8b616c76 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 17 Jul 2013 14:45:34 +0200 +Subject: [PATCH 32/38] qcow2: Use dashes instead of underscores in options + +Message-id: <1378736903-18489-33-git-send-email-kwolf@redhat.com> +Patchwork-id: 54219 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 32/32] qcow2: Use dashes instead of underscores in options +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This is what QMP wants to use. The options haven't been enabled in any +release yet, so we're still free to change them. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 64aa99d3e0333dea73d7505190659a02ca909292) + +Signed-off-by: Kevin Wolf +--- + block/qcow2.c | 2 +- + block/qcow2.h | 8 ++++---- + tests/qemu-iotests/051 | 14 +++++++------- + tests/qemu-iotests/051.out | 30 +++++++++++++++--------------- + 4 files changed, 27 insertions(+), 27 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 9383990..abdc202 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -291,7 +291,7 @@ static QemuOptsList qcow2_runtime_opts = { + .head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head), + .desc = { + { +- .name = "lazy_refcounts", ++ .name = QCOW2_OPT_LAZY_REFCOUNTS, + .type = QEMU_OPT_BOOL, + .help = "Postpone refcount updates", + }, +diff --git a/block/qcow2.h b/block/qcow2.h +index 3b2d5cd..dba9771 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -59,10 +59,10 @@ + #define DEFAULT_CLUSTER_SIZE 65536 + + +-#define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts" +-#define QCOW2_OPT_DISCARD_REQUEST "pass_discard_request" +-#define QCOW2_OPT_DISCARD_SNAPSHOT "pass_discard_snapshot" +-#define QCOW2_OPT_DISCARD_OTHER "pass_discard_other" ++#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts" ++#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request" ++#define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot" ++#define QCOW2_OPT_DISCARD_OTHER "pass-discard-other" + + typedef struct QCowHeader { + uint32_t magic; +diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 +index 1cf8bf7..1f39c6a 100755 +--- a/tests/qemu-iotests/051 ++++ b/tests/qemu-iotests/051 +@@ -72,11 +72,11 @@ echo + echo === Enable and disable lazy refcounting on the command line, plus some invalid values === + echo + +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts= +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=42 +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=foo ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts= ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=42 ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=foo + + + echo +@@ -85,8 +85,8 @@ echo + + _make_test_img -ocompat=0.10 $size + +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on ++run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off + + echo + echo === No medium === +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 8630382..9588d0c 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -22,35 +22,35 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not + + === Enable and disable lazy refcounting on the command line, plus some invalid values === + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts= +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: Parameter 'lazy_refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts= ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off' ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42 +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: Parameter 'lazy_refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42 ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: Parameter 'lazy-refcounts' expects 'on' or 'off' ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: Parameter 'lazy_refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: Parameter 'lazy-refcounts' expects 'on' or 'off' ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument + + + === With version 2 images enabling lazy refcounts must fail === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument + +-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off ++Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off + QEMU 1.5.50 monitor - type 'help' for more information + (qemu) qququiquit + +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Use-negated-overflow-check-mask.patch b/SOURCES/kvm-qcow2-Use-negated-overflow-check-mask.patch new file mode 100644 index 0000000..1e239b0 --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-negated-overflow-check-mask.patch @@ -0,0 +1,262 @@ +From ca635f6c3ae10562a2165590bb84667aa61ad12f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:29 +0100 +Subject: [PATCH 36/87] qcow2: Use negated overflow check mask + +RH-Author: Max Reitz +Message-id: <1383604354-12743-39-git-send-email-mreitz@redhat.com> +Patchwork-id: 55338 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 38/43] qcow2: Use negated overflow check mask +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +In qcow2_check_metadata_overlap and qcow2_pre_write_overlap_check, +change the parameter signifying the checks to perform from its current +positive form to a negative one, i.e., it will no longer explicitly +specify every check to perform but rather a mask of checks not to +perform. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 231bb267644ee3a9ebfd9c7f42d5d41610194b45) + +Signed-off-by: Max Reitz + +Conflicts: + block/qcow2-cluster.c + +Conflicts because downstream does not contain +expand_zero_clusters_in_l1(). +--- + block/qcow2-cache.c | 8 +++----- + block/qcow2-cluster.c | 9 ++++----- + block/qcow2-refcount.c | 22 ++++++++++------------ + block/qcow2-snapshot.c | 12 +++++------- + block/qcow2.c | 5 ++--- + block/qcow2.h | 4 ++-- + 6 files changed, 26 insertions(+), 34 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cache.c | 8 +++----- + block/qcow2-cluster.c | 9 ++++----- + block/qcow2-refcount.c | 22 ++++++++++------------ + block/qcow2-snapshot.c | 12 +++++------- + block/qcow2.c | 5 ++--- + block/qcow2.h | 4 ++-- + 6 files changed, 26 insertions(+), 34 deletions(-) + +diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c +index 7bcae09..eb1d69b 100644 +--- a/block/qcow2-cache.c ++++ b/block/qcow2-cache.c +@@ -115,15 +115,13 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i) + } + + if (c == s->refcount_block_cache) { +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_BLOCK, ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_REFCOUNT_BLOCK, + c->entries[i].offset, s->cluster_size); + } else if (c == s->l2_table_cache) { +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2, + c->entries[i].offset, s->cluster_size); + } else { +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ ret = qcow2_pre_write_overlap_check(bs, 0, + c->entries[i].offset, s->cluster_size); + } + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index c05f182..5d13515 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -83,8 +83,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + + /* the L1 position has not yet been updated, so these clusters must + * indeed be completely free */ +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +- new_l1_table_offset, new_l1_size2); ++ ret = qcow2_pre_write_overlap_check(bs, 0, new_l1_table_offset, ++ new_l1_size2); + if (ret < 0) { + goto fail; + } +@@ -160,8 +160,7 @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) + buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]); + } + +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1, ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1, + s->l1_table_offset + 8 * l1_start_index, sizeof(buf)); + if (ret < 0) { + return ret; +@@ -386,7 +385,7 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs, + &s->aes_encrypt_key); + } + +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ ret = qcow2_pre_write_overlap_check(bs, 0, + cluster_offset + n_start * BDRV_SECTOR_SIZE, n * BDRV_SECTOR_SIZE); + if (ret < 0) { + goto out; +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 5c5683d..91c446b 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1291,9 +1291,8 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, + } + + if (l2_dirty) { +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset, +- s->cluster_size); ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L2, ++ l2_offset, s->cluster_size); + if (ret < 0) { + fprintf(stderr, "ERROR: Could not write L2 table; metadata " + "overlap check failed: %s\n", strerror(-ret)); +@@ -1334,8 +1333,7 @@ static int write_reftable_entry(BlockDriverState *bs, int rt_index) + buf[i] = cpu_to_be64(s->refcount_table[rt_start_index + i]); + } + +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_REFCOUNT_TABLE, ++ 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) { +@@ -1386,8 +1384,7 @@ static int64_t realloc_refcount_block(BlockDriverState *bs, int reftable_index, + + /* 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, QCOW2_OL_DEFAULT, new_offset, +- s->cluster_size); ++ 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)); +@@ -1619,8 +1616,8 @@ fail: + * looking for overlaps with important metadata sections (L1/L2 tables etc.), + * i.e. a sanity check without relying on the refcount tables. + * +- * The chk parameter specifies exactly what checks to perform (being a bitmask +- * of QCow2MetadataOverlap values). ++ * The ign parameter specifies what checks not to perform (being a bitmask of ++ * QCow2MetadataOverlap values), i.e., what sections to ignore. + * + * Returns: + * - 0 if writing to this offset will not affect the mentioned metadata +@@ -1628,10 +1625,11 @@ fail: + * - a negative value (-errno) indicating an error while performing a check, + * e.g. when bdrv_read failed on QCOW2_OL_INACTIVE_L2 + */ +-int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, ++int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, + int64_t size) + { + BDRVQcowState *s = bs->opaque; ++ int chk = QCOW2_OL_DEFAULT & ~ign; + int i, j; + + if (!size) { +@@ -1747,10 +1745,10 @@ static const char *metadata_ol_names[] = { + * Returns 0 if there were neither overlaps nor errors while checking for + * overlaps; or a negative value (-errno) on error. + */ +-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset, ++int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, + int64_t size) + { +- int ret = qcow2_check_metadata_overlap(bs, chk, offset, size); ++ int ret = qcow2_check_metadata_overlap(bs, ign, offset, size); + + if (ret < 0) { + return ret; +diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c +index 450e4f5..aa88c51 100644 +--- a/block/qcow2-snapshot.c ++++ b/block/qcow2-snapshot.c +@@ -191,8 +191,7 @@ static int qcow2_write_snapshots(BlockDriverState *bs) + + /* The snapshot list position has not yet been updated, so these clusters + * must indeed be completely free */ +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, offset, +- snapshots_size); ++ ret = qcow2_pre_write_overlap_check(bs, 0, offset, snapshots_size); + if (ret < 0) { + return ret; + } +@@ -372,8 +371,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) + l1_table[i] = cpu_to_be64(s->l1_table[i]); + } + +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +- sn->l1_table_offset, s->l1_size * sizeof(uint64_t)); ++ ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset, ++ s->l1_size * sizeof(uint64_t)); + if (ret < 0) { + goto fail; + } +@@ -490,9 +489,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) + goto fail; + } + +- ret = qcow2_pre_write_overlap_check(bs, +- QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L1, +- s->l1_table_offset, cur_l1_bytes); ++ ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1, ++ s->l1_table_offset, cur_l1_bytes); + if (ret < 0) { + goto fail; + } +diff --git a/block/qcow2.c b/block/qcow2.c +index 8b73518..ac5ed47 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -964,7 +964,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState *bs, + cur_nr_sectors * 512); + } + +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, ++ ret = qcow2_pre_write_overlap_check(bs, 0, + cluster_offset + index_in_cluster * BDRV_SECTOR_SIZE, + cur_nr_sectors * BDRV_SECTOR_SIZE); + if (ret < 0) { +@@ -1748,8 +1748,7 @@ static int qcow2_write_compressed(BlockDriverState *bs, int64_t sector_num, + } + cluster_offset &= s->cluster_offset_mask; + +- ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_DEFAULT, +- cluster_offset, out_len); ++ ret = qcow2_pre_write_overlap_check(bs, 0, cluster_offset, out_len); + if (ret < 0) { + goto fail; + } +diff --git a/block/qcow2.h b/block/qcow2.h +index 10b7bf4..64ad43c 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -424,9 +424,9 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + + void qcow2_process_discards(BlockDriverState *bs, int ret); + +-int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, ++int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, + int64_t size); +-int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset, ++int qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offset, + int64_t size); + + /* qcow2-cluster.c functions */ +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-Use-pread-for-inactive-L1-in-overlap-check.patch b/SOURCES/kvm-qcow2-Use-pread-for-inactive-L1-in-overlap-check.patch new file mode 100644 index 0000000..f4061bd --- /dev/null +++ b/SOURCES/kvm-qcow2-Use-pread-for-inactive-L1-in-overlap-check.patch @@ -0,0 +1,61 @@ +From 712a6ef0d0d3bbc91953305ad8e7e96f82f19cf0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:27 +0100 +Subject: [PATCH 34/87] qcow2: Use pread for inactive L1 in overlap check + +RH-Author: Max Reitz +Message-id: <1383604354-12743-37-git-send-email-mreitz@redhat.com> +Patchwork-id: 55336 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 36/43] qcow2: Use pread for inactive L1 in overlap check +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Currently, qcow2_check_metadata_overlap uses bdrv_read to read inactive +L1 tables from disk. The number of sectors to read is calculated through +a truncating integer division, therefore, if the L1 table size is not a +multiple of the sector size, the final entries will not be read and +their entries in memory remain undefined (from the g_malloc). +Using bdrv_pread fixes this. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 998b959c1e59044f5d5f64c482f4ce8facc8e0bc) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 7 +++---- + 1 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 34fcf2f..5c5683d 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1701,12 +1701,11 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int chk, int64_t offset, + for (i = 0; i < s->nb_snapshots; i++) { + uint64_t l1_ofs = s->snapshots[i].l1_table_offset; + uint32_t l1_sz = s->snapshots[i].l1_size; +- uint64_t *l1 = g_malloc(l1_sz * sizeof(uint64_t)); ++ uint64_t l1_sz2 = l1_sz * sizeof(uint64_t); ++ uint64_t *l1 = g_malloc(l1_sz2); + int ret; + +- ret = bdrv_read(bs->file, l1_ofs / BDRV_SECTOR_SIZE, (uint8_t *)l1, +- l1_sz * sizeof(uint64_t) / BDRV_SECTOR_SIZE); +- ++ ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2); + if (ret < 0) { + g_free(l1); + return ret; +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-refcount-Move-OFLAG_COPIED-checks.patch b/SOURCES/kvm-qcow2-refcount-Move-OFLAG_COPIED-checks.patch new file mode 100644 index 0000000..a03fcd1 --- /dev/null +++ b/SOURCES/kvm-qcow2-refcount-Move-OFLAG_COPIED-checks.patch @@ -0,0 +1,201 @@ +From 27a96310e27b1b3880935430d58330a90ccc0176 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:02 +0100 +Subject: [PATCH 09/87] qcow2-refcount: Move OFLAG_COPIED checks + +RH-Author: Max Reitz +Message-id: <1383604354-12743-12-git-send-email-mreitz@redhat.com> +Patchwork-id: 55311 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 11/43] qcow2-refcount: Move OFLAG_COPIED checks +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Move the OFLAG_COPIED checks out of check_refcounts_l1 and +check_refcounts_l2 and after the actual refcount checks/fixes (since the +refcounts might actually change there). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 4f6ed88c03c4026e31ce152ea760a0da839f0dda) + +Signed-off-by: Max Reitz +--- + block/qcow2-refcount.c | 115 +++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 82 insertions(+), 33 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-refcount.c | 115 ++++++++++++++++++++++++++++++++++-------------- + 1 files changed, 82 insertions(+), 33 deletions(-) + +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 310efcc..ddc3029 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1035,7 +1035,7 @@ 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, refcount; ++ int i, l2_size, nb_csectors; + + /* Read L2 table from disk */ + l2_size = s->l2_size * sizeof(uint64_t); +@@ -1087,23 +1087,8 @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res, + + case QCOW2_CLUSTER_NORMAL: + { +- /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ + uint64_t offset = l2_entry & L2E_OFFSET_MASK; + +- if (flags & CHECK_OFLAG_COPIED) { +- refcount = get_refcount(bs, offset >> s->cluster_bits); +- if (refcount < 0) { +- fprintf(stderr, "Can't get refcount for offset %" +- PRIx64 ": %s\n", l2_entry, strerror(-refcount)); +- goto fail; +- } +- if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { +- fprintf(stderr, "ERROR OFLAG_COPIED: offset=%" +- PRIx64 " refcount=%d\n", l2_entry, refcount); +- res->corruptions++; +- } +- } +- + if (flags & CHECK_FRAG_INFO) { + res->bfi.allocated_clusters++; + if (next_contiguous_offset && +@@ -1160,7 +1145,7 @@ static int check_refcounts_l1(BlockDriverState *bs, + { + BDRVQcowState *s = bs->opaque; + uint64_t *l1_table, l2_offset, l1_size2; +- int i, refcount, ret; ++ int i, ret; + + l1_size2 = l1_size * sizeof(uint64_t); + +@@ -1184,22 +1169,6 @@ static int check_refcounts_l1(BlockDriverState *bs, + for(i = 0; i < l1_size; i++) { + l2_offset = l1_table[i]; + if (l2_offset) { +- /* QCOW_OFLAG_COPIED must be set iff refcount == 1 */ +- if (flags & CHECK_OFLAG_COPIED) { +- refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) +- >> s->cluster_bits); +- if (refcount < 0) { +- fprintf(stderr, "Can't get refcount for l2_offset %" +- PRIx64 ": %s\n", l2_offset, strerror(-refcount)); +- goto fail; +- } +- if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) { +- fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64 +- " refcount=%d\n", l2_offset, refcount); +- res->corruptions++; +- } +- } +- + /* Mark L2 table as used */ + l2_offset &= L1E_OFFSET_MASK; + inc_refcounts(bs, res, refcount_table, refcount_table_size, +@@ -1231,6 +1200,80 @@ fail: + } + + /* ++ * Checks the OFLAG_COPIED flag for all L1 and L2 entries. ++ * ++ * This function does not print an error message nor does it increment ++ * check_errors if get_refcount fails (this is because such an error will have ++ * been already detected and sufficiently signaled by the calling function ++ * (qcow2_check_refcounts) by the time this function is called). ++ */ ++static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) ++{ ++ BDRVQcowState *s = bs->opaque; ++ uint64_t *l2_table = qemu_blockalign(bs, s->cluster_size); ++ int ret; ++ int refcount; ++ int i, j; ++ ++ for (i = 0; i < s->l1_size; i++) { ++ uint64_t l1_entry = s->l1_table[i]; ++ uint64_t l2_offset = l1_entry & L1E_OFFSET_MASK; ++ ++ if (!l2_offset) { ++ continue; ++ } ++ ++ refcount = get_refcount(bs, l2_offset >> s->cluster_bits); ++ if (refcount < 0) { ++ /* don't print message nor increment check_errors */ ++ continue; ++ } ++ if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) { ++ fprintf(stderr, "ERROR OFLAG_COPIED L2 cluster: l1_index=%d " ++ "l1_entry=%" PRIx64 " refcount=%d\n", ++ i, l1_entry, refcount); ++ res->corruptions++; ++ } ++ ++ ret = bdrv_pread(bs->file, l2_offset, l2_table, ++ s->l2_size * sizeof(uint64_t)); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: Could not read L2 table: %s\n", ++ strerror(-ret)); ++ res->check_errors++; ++ goto fail; ++ } ++ ++ for (j = 0; j < s->l2_size; j++) { ++ uint64_t l2_entry = be64_to_cpu(l2_table[j]); ++ uint64_t data_offset = l2_entry & L2E_OFFSET_MASK; ++ int cluster_type = qcow2_get_cluster_type(l2_entry); ++ ++ if ((cluster_type == QCOW2_CLUSTER_NORMAL) || ++ ((cluster_type == QCOW2_CLUSTER_ZERO) && (data_offset != 0))) { ++ refcount = get_refcount(bs, data_offset >> s->cluster_bits); ++ if (refcount < 0) { ++ /* don't print message nor increment check_errors */ ++ continue; ++ } ++ if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { ++ fprintf(stderr, "ERROR OFLAG_COPIED data cluster: " ++ "l2_entry=%" PRIx64 " refcount=%d\n", ++ l2_entry, refcount); ++ res->corruptions++; ++ } ++ } ++ } ++ } ++ ++ ret = 0; ++ ++fail: ++ qemu_vfree(l2_table); ++ return ret; ++} ++ ++/* + * Checks an image for refcount consistency. + * + * Returns 0 if no errors are found, the number of errors in case the image is +@@ -1365,6 +1408,12 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + } + ++ /* check OFLAG_COPIED */ ++ ret = check_oflag_copied(bs, res); ++ if (ret < 0) { ++ goto fail; ++ } ++ + res->image_end_offset = (highest_cluster + 1) * s->cluster_size; + ret = 0; + +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-refcount-Repair-OFLAG_COPIED-errors.patch b/SOURCES/kvm-qcow2-refcount-Repair-OFLAG_COPIED-errors.patch new file mode 100644 index 0000000..2b90310 --- /dev/null +++ b/SOURCES/kvm-qcow2-refcount-Repair-OFLAG_COPIED-errors.patch @@ -0,0 +1,182 @@ +From 7f0500dff4d7da11bda309de3866851f382f6fe8 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:03 +0100 +Subject: [PATCH 10/87] qcow2-refcount: Repair OFLAG_COPIED errors + +RH-Author: Max Reitz +Message-id: <1383604354-12743-13-git-send-email-mreitz@redhat.com> +Patchwork-id: 55312 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 12/43] qcow2-refcount: Repair OFLAG_COPIED errors +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Since the OFLAG_COPIED checks are now executed after the refcounts have +been repaired (if repairing), it is safe to assume that they are correct +but the OFLAG_COPIED flag may be not. Therefore, if its value differs +from what it should be (considering the according refcount), that +discrepancy can be repaired by correctly setting (or clearing that flag. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit e23e400ec62a03dea58ddb38479b4f1ef86f556d) + +Signed-off-by: Max Reitz +--- + block/qcow2-cluster.c | 4 ++-- + block/qcow2-refcount.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------ + block/qcow2.h | 1 + + 3 files changed, 55 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2-cluster.c | 4 +- + block/qcow2-refcount.c | 58 +++++++++++++++++++++++++++++++++++++++++++----- + block/qcow2.h | 1 + + 3 files changed, 55 insertions(+), 8 deletions(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index 7c248aa..2d5aa92 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -145,7 +145,7 @@ static int l2_load(BlockDriverState *bs, uint64_t l2_offset, + * and we really don't want bdrv_pread to perform a read-modify-write) + */ + #define L1_ENTRIES_PER_SECTOR (512 / 8) +-static int write_l1_entry(BlockDriverState *bs, int l1_index) ++int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index) + { + BDRVQcowState *s = bs->opaque; + uint64_t buf[L1_ENTRIES_PER_SECTOR]; +@@ -254,7 +254,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table) + /* update the L1 entry */ + trace_qcow2_l2_allocate_write_l1(bs, l1_index); + s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; +- ret = write_l1_entry(bs, l1_index); ++ ret = qcow2_write_l1_entry(bs, l1_index); + if (ret < 0) { + goto fail; + } +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index ddc3029..92ecc64 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1207,7 +1207,8 @@ fail: + * been already detected and sufficiently signaled by the calling function + * (qcow2_check_refcounts) by the time this function is called). + */ +-static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) ++static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res, ++ BdrvCheckMode fix) + { + BDRVQcowState *s = bs->opaque; + uint64_t *l2_table = qemu_blockalign(bs, s->cluster_size); +@@ -1218,6 +1219,7 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) + for (i = 0; i < s->l1_size; i++) { + uint64_t l1_entry = s->l1_table[i]; + uint64_t l2_offset = l1_entry & L1E_OFFSET_MASK; ++ bool l2_dirty = false; + + if (!l2_offset) { + continue; +@@ -1229,10 +1231,24 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) + continue; + } + if ((refcount == 1) != ((l1_entry & QCOW_OFLAG_COPIED) != 0)) { +- fprintf(stderr, "ERROR OFLAG_COPIED L2 cluster: l1_index=%d " ++ fprintf(stderr, "%s OFLAG_COPIED L2 cluster: l1_index=%d " + "l1_entry=%" PRIx64 " refcount=%d\n", ++ fix & BDRV_FIX_ERRORS ? "Repairing" : ++ "ERROR", + i, l1_entry, refcount); +- res->corruptions++; ++ if (fix & BDRV_FIX_ERRORS) { ++ s->l1_table[i] = refcount == 1 ++ ? l1_entry | QCOW_OFLAG_COPIED ++ : l1_entry & ~QCOW_OFLAG_COPIED; ++ ret = qcow2_write_l1_entry(bs, i); ++ if (ret < 0) { ++ res->check_errors++; ++ goto fail; ++ } ++ res->corruptions_fixed++; ++ } else { ++ res->corruptions++; ++ } + } + + ret = bdrv_pread(bs->file, l2_offset, l2_table, +@@ -1257,13 +1273,43 @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res) + continue; + } + if ((refcount == 1) != ((l2_entry & QCOW_OFLAG_COPIED) != 0)) { +- fprintf(stderr, "ERROR OFLAG_COPIED data cluster: " ++ fprintf(stderr, "%s OFLAG_COPIED data cluster: " + "l2_entry=%" PRIx64 " refcount=%d\n", ++ fix & BDRV_FIX_ERRORS ? "Repairing" : ++ "ERROR", + l2_entry, refcount); +- res->corruptions++; ++ if (fix & BDRV_FIX_ERRORS) { ++ l2_table[j] = cpu_to_be64(refcount == 1 ++ ? l2_entry | QCOW_OFLAG_COPIED ++ : l2_entry & ~QCOW_OFLAG_COPIED); ++ l2_dirty = true; ++ res->corruptions_fixed++; ++ } else { ++ res->corruptions++; ++ } + } + } + } ++ ++ if (l2_dirty) { ++ ret = qcow2_pre_write_overlap_check(bs, ++ QCOW2_OL_DEFAULT & ~QCOW2_OL_ACTIVE_L2, l2_offset, ++ s->cluster_size); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: Could not write L2 table; metadata " ++ "overlap check failed: %s\n", strerror(-ret)); ++ res->check_errors++; ++ goto fail; ++ } ++ ++ ret = bdrv_pwrite(bs->file, l2_offset, l2_table, s->cluster_size); ++ if (ret < 0) { ++ fprintf(stderr, "ERROR: Could not write L2 table: %s\n", ++ strerror(-ret)); ++ res->check_errors++; ++ goto fail; ++ } ++ } + } + + ret = 0; +@@ -1409,7 +1455,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + } + + /* check OFLAG_COPIED */ +- ret = check_oflag_copied(bs, res); ++ ret = check_oflag_copied(bs, res, fix); + if (ret < 0) { + goto fail; + } +diff --git a/block/qcow2.h b/block/qcow2.h +index 86ddb30..10b7bf4 100644 +--- a/block/qcow2.h ++++ b/block/qcow2.h +@@ -432,6 +432,7 @@ int qcow2_pre_write_overlap_check(BlockDriverState *bs, int chk, int64_t offset, + /* qcow2-cluster.c functions */ + int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, + bool exact_size); ++int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index); + void qcow2_l2_cache_reset(BlockDriverState *bs); + int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); + void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2-refcount-Repair-shared-refcount-blocks.patch b/SOURCES/kvm-qcow2-refcount-Repair-shared-refcount-blocks.patch new file mode 100644 index 0000000..7ce63b7 --- /dev/null +++ b/SOURCES/kvm-qcow2-refcount-Repair-shared-refcount-blocks.patch @@ -0,0 +1,233 @@ +From d4803ddf6139cf2ad7e2d53035b5f828da97b51c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:04 +0100 +Subject: [PATCH 11/87] qcow2-refcount: Repair shared refcount blocks + +RH-Author: Max Reitz +Message-id: <1383604354-12743-14-git-send-email-mreitz@redhat.com> +Patchwork-id: 55313 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 13/43] qcow2-refcount: Repair shared refcount blocks +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +If the refcount of a refcount block is greater than one, we can at least +try to repair that problem by duplicating the affected block. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit afa50193cde574528a130a25544fd6f3aa8da069) + +Signed-off-by: Max Reitz +--- + block/blkdebug.c | 1 + + block/qcow2-refcount.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++- + include/block/block.h | 1 + + 3 files changed, 148 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/blkdebug.c | 1 + + block/qcow2-refcount.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++- + include/block/block.h | 1 + + 3 files changed, 148 insertions(+), 2 deletions(-) + +diff --git a/block/blkdebug.c b/block/blkdebug.c +index 71f99e4..d659d38 100644 +--- a/block/blkdebug.c ++++ b/block/blkdebug.c +@@ -168,6 +168,7 @@ static const char *event_names[BLKDBG_EVENT_MAX] = { + + [BLKDBG_REFTABLE_LOAD] = "reftable_load", + [BLKDBG_REFTABLE_GROW] = "reftable_grow", ++ [BLKDBG_REFTABLE_UPDATE] = "reftable_update", + + [BLKDBG_REFBLOCK_LOAD] = "refblock_load", + [BLKDBG_REFBLOCK_UPDATE] = "refblock_update", +diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c +index 92ecc64..927bdeb 100644 +--- a/block/qcow2-refcount.c ++++ b/block/qcow2-refcount.c +@@ -1320,6 +1320,121 @@ 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_DEFAULT & ~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, QCOW2_OL_DEFAULT, 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 an image for refcount consistency. + * + * Returns 0 if no errors are found, the number of errors in case the image is +@@ -1395,10 +1510,39 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, + inc_refcounts(bs, res, refcount_table, nb_clusters, + offset, s->cluster_size); + if (refcount_table[cluster] != 1) { +- fprintf(stderr, "ERROR refcount block %" PRId64 ++ fprintf(stderr, "%s refcount block %" PRId64 + " refcount=%d\n", ++ fix & BDRV_FIX_ERRORS ? "Repairing" : ++ "ERROR", + i, refcount_table[cluster]); +- res->corruptions++; ++ ++ 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_realloc(refcount_table, ++ nb_clusters * sizeof(uint16_t)); ++ 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, ++ new_offset, s->cluster_size); ++ ++ res->corruptions_fixed++; ++ } else { ++ res->corruptions++; ++ } + } + } + } +diff --git a/include/block/block.h b/include/block/block.h +index 03ebc47..39770a3 100644 +--- a/include/block/block.h ++++ b/include/block/block.h +@@ -447,6 +447,7 @@ typedef enum { + + BLKDBG_REFTABLE_LOAD, + BLKDBG_REFTABLE_GROW, ++ BLKDBG_REFTABLE_UPDATE, + + BLKDBG_REFBLOCK_LOAD, + BLKDBG_REFBLOCK_UPDATE, +-- +1.7.1 + diff --git a/SOURCES/kvm-qcow2_check-Mark-image-consistent.patch b/SOURCES/kvm-qcow2_check-Mark-image-consistent.patch new file mode 100644 index 0000000..e4d0b51 --- /dev/null +++ b/SOURCES/kvm-qcow2_check-Mark-image-consistent.patch @@ -0,0 +1,54 @@ +From 08183017ea26569bd0ab226576e9772c768a65e7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:05 +0100 +Subject: [PATCH 12/87] qcow2_check: Mark image consistent + +RH-Author: Max Reitz +Message-id: <1383604354-12743-15-git-send-email-mreitz@redhat.com> +Patchwork-id: 55314 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 14/43] qcow2_check: Mark image consistent +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +If no corruptions remain after an image repair (and no errors have been +encountered), clear the corrupt flag in qcow2_check. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 24530f3e060c71b6c57c7a70336f08a13a8b0a3d) + +Signed-off-by: Max Reitz +--- + block/qcow2.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qcow2.c | 6 +++++- + 1 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/block/qcow2.c b/block/qcow2.c +index 90950cb..8a30863 100644 +--- a/block/qcow2.c ++++ b/block/qcow2.c +@@ -312,7 +312,11 @@ static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result, + } + + if (fix && result->check_errors == 0 && result->corruptions == 0) { +- return qcow2_mark_clean(bs); ++ ret = qcow2_mark_clean(bs); ++ if (ret < 0) { ++ return ret; ++ } ++ return qcow2_mark_consistent(bs); + } + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qdev-Do-not-let-the-user-try-to-device_add-when-it-c.patch b/SOURCES/kvm-qdev-Do-not-let-the-user-try-to-device_add-when-it-c.patch new file mode 100644 index 0000000..63af405 --- /dev/null +++ b/SOURCES/kvm-qdev-Do-not-let-the-user-try-to-device_add-when-it-c.patch @@ -0,0 +1,65 @@ +From de651299014ae67b110a2abbff4a9e544b215b2b Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:21 +0100 +Subject: [PATCH 45/81] qdev: Do not let the user try to device_add when it cannot work + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-17-git-send-email-kwolf@redhat.com> +Patchwork-id: 55542 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 16/17] qdev: Do not let the user try to device_add when it cannot work +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Such devices have always been unavailable and omitted from the list of +available devices shown by device_add help. Until commit 18b6dad +silently broke the former, setting up nasty traps for unwary users, +like this one: + + $ qemu-system-x86_64 -nodefaults -monitor stdio -display none + QEMU 1.6.50 monitor - type 'help' for more information + (qemu) device_add apic + Segmentation fault (core dumped) + +I call that a regression. Fix it. +(cherry picked from pending upstream submission) + +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + qdev-monitor.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qdev-monitor.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/qdev-monitor.c b/qdev-monitor.c +index f54cb21..39d030b 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -477,13 +477,13 @@ DeviceState *qdev_device_add(QemuOpts *opts) + } + } + +- if (!obj) { ++ k = DEVICE_CLASS(obj); ++ ++ if (!k || k->cannot_instantiate_with_device_add_yet) { + qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type"); + return NULL; + } + +- k = DEVICE_CLASS(obj); +- + /* find bus */ + path = qemu_opt_get(opts, "bus"); + if (path != NULL) { +-- +1.7.1 + diff --git a/SOURCES/kvm-qdev-Replace-no_user-by-cannot_instantiate_with_devi.patch b/SOURCES/kvm-qdev-Replace-no_user-by-cannot_instantiate_with_devi.patch new file mode 100644 index 0000000..4782eeb --- /dev/null +++ b/SOURCES/kvm-qdev-Replace-no_user-by-cannot_instantiate_with_devi.patch @@ -0,0 +1,928 @@ +From 3e04367b75615f4b1b53350b875c5c14b68dc785 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:12 +0100 +Subject: [PATCH 36/81] qdev: Replace no_user by cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-8-git-send-email-kwolf@redhat.com> +Patchwork-id: 55533 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 07/17] qdev: Replace no_user by cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +In an ideal world, machines can be built by wiring devices together +with configuration, not code. Unfortunately, that's not the world we +live in right now. We still have quite a few devices that need to be +wired up by code. If you try to device_add such a device, it'll fail +in sometimes mysterious ways. If you're lucky, you get an +unmysterious immediate crash. + +To protect users from such badness, DeviceClass member no_user used to +make device models unavailable with -device / device_add, but that +regressed in commit 18b6dad. The device model is still omitted from +help, but is available anyway. + +Attempts to fix the regression have been rejected with the argument +that the purpose of no_user isn't clear, and it's prone to misuse. + +This commit clarifies no_user's purpose. Anthony suggested to rename +it cannot_instantiate_with_device_add_yet_due_to_internal_bugs, which +I shorten somewhat to keep checkpatch happy. While there, make it +bool. + +Every use of cannot_instantiate_with_device_add_yet gets a FIXME +comment asking for rationale. The next few commits will clean them +all up, either by providing a rationale, or by getting rid of the use. + +With that done, the regression fix is hopefully acceptable. + +Signed-off-by: Markus Armbruster +Reviewed-by: Marcel Apfelbaum +(cherry picked from pending upstream submission) + +Conflicts: + hw/dma/pl080.c + hw/i386/kvm/clock.c + hw/i386/pc.c + hw/input/pckbd.c + hw/input/vmmouse.c + hw/misc/vmport.c + hw/nvram/fw_cfg.c + hw/pci-host/piix.c + hw/timer/hpet.c + hw/timer/m48t59.c + hw/timer/mc146818rtc.c + +A few more semantic conflicts elsewhere. Conflict resolution is +always the same: replace just no_user, keep context intact. +Signed-off-by: Kevin Wolf +--- + hw/acpi/piix4.c | 2 +- + hw/alpha/typhoon.c | 2 +- + hw/arm/versatilepb.c | 2 +- + hw/audio/pcspk.c | 2 +- + hw/audio/pl041.c | 2 +- + hw/block/fdc.c | 2 +- + hw/display/pl110.c | 6 +++--- + hw/dma/pl080.c | 4 ++-- + hw/i2c/smbus_ich9.c | 2 +- + hw/i386/kvm/clock.c | 2 +- + hw/i386/kvmvapic.c | 2 +- + hw/i386/pc.c | 2 +- + hw/ide/piix.c | 6 +++--- + hw/ide/via.c | 2 +- + hw/input/pckbd.c | 2 +- + hw/input/vmmouse.c | 2 +- + hw/intc/apic_common.c | 2 +- + hw/intc/arm_gic.c | 2 +- + hw/intc/arm_gic_common.c | 2 +- + hw/intc/arm_gic_kvm.c | 2 +- + hw/intc/i8259_common.c | 2 +- + hw/intc/ioapic_common.c | 2 +- + hw/intc/pl190.c | 2 +- + hw/isa/isa-bus.c | 2 +- + hw/isa/lpc_ich9.c | 2 +- + hw/isa/piix4.c | 2 +- + hw/isa/vt82c686.c | 2 +- + hw/misc/arm_l2x0.c | 2 +- + hw/misc/pvpanic.c | 2 +- + hw/misc/vmport.c | 2 +- + hw/nvram/fw_cfg.c | 2 +- + hw/pci-host/bonito.c | 4 ++-- + hw/pci-host/grackle.c | 4 ++-- + hw/pci-host/piix.c | 8 ++++---- + hw/pci-host/prep.c | 4 ++-- + hw/ppc/spapr_vio.c | 2 +- + hw/s390x/ipl.c | 2 +- + hw/s390x/s390-virtio-bus.c | 2 +- + hw/s390x/virtio-ccw.c | 2 +- + hw/sd/pl181.c | 2 +- + hw/timer/arm_mptimer.c | 2 +- + hw/timer/hpet.c | 2 +- + hw/timer/i8254_common.c | 2 +- + hw/timer/m48t59.c | 2 +- + hw/timer/mc146818rtc.c | 2 +- + hw/timer/pl031.c | 2 +- + include/hw/qdev-core.h | 13 ++++++++++++- + qdev-monitor.c | 5 +++-- + qom/cpu.c | 2 +- + 49 files changed, 73 insertions(+), 61 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/acpi/piix4.c | 2 +- + hw/alpha/typhoon.c | 2 +- + hw/arm/versatilepb.c | 2 +- + hw/audio/pcspk.c | 2 +- + hw/audio/pl041.c | 2 +- + hw/block/fdc.c | 2 +- + hw/display/pl110.c | 6 +++--- + hw/dma/pl080.c | 4 ++-- + hw/i2c/smbus_ich9.c | 2 +- + hw/i386/kvm/clock.c | 2 +- + hw/i386/kvmvapic.c | 2 +- + hw/i386/pc.c | 2 +- + hw/ide/piix.c | 6 +++--- + hw/ide/via.c | 2 +- + hw/input/pckbd.c | 2 +- + hw/input/vmmouse.c | 2 +- + hw/intc/apic_common.c | 2 +- + hw/intc/arm_gic.c | 2 +- + hw/intc/arm_gic_common.c | 2 +- + hw/intc/arm_gic_kvm.c | 2 +- + hw/intc/i8259_common.c | 2 +- + hw/intc/ioapic_common.c | 2 +- + hw/intc/pl190.c | 2 +- + hw/isa/isa-bus.c | 2 +- + hw/isa/lpc_ich9.c | 2 +- + hw/isa/piix4.c | 2 +- + hw/isa/vt82c686.c | 2 +- + hw/misc/arm_l2x0.c | 2 +- + hw/misc/pvpanic.c | 2 +- + hw/misc/vmport.c | 2 +- + hw/nvram/fw_cfg.c | 2 +- + hw/pci-host/bonito.c | 4 ++-- + hw/pci-host/grackle.c | 4 ++-- + hw/pci-host/piix.c | 8 ++++---- + hw/pci-host/prep.c | 4 ++-- + hw/ppc/spapr_vio.c | 2 +- + hw/s390x/ipl.c | 2 +- + hw/s390x/s390-virtio-bus.c | 2 +- + hw/s390x/virtio-ccw.c | 2 +- + hw/sd/pl181.c | 2 +- + hw/timer/arm_mptimer.c | 2 +- + hw/timer/hpet.c | 2 +- + hw/timer/i8254_common.c | 2 +- + hw/timer/m48t59.c | 2 +- + hw/timer/mc146818rtc.c | 2 +- + hw/timer/pl031.c | 2 +- + include/hw/qdev-core.h | 13 ++++++++++++- + qdev-monitor.c | 5 +++-- + qom/cpu.c | 2 +- + 49 files changed, 73 insertions(+), 61 deletions(-) + +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index f14867a..46685b7 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -494,7 +494,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data) + k->revision = 0x03; + k->class_id = PCI_CLASS_BRIDGE_OTHER; + dc->desc = "PM"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_acpi; + dc->props = piix4_pm_properties; + } +diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c +index 1ead187..55a0e76 100644 +--- a/hw/alpha/typhoon.c ++++ b/hw/alpha/typhoon.c +@@ -823,7 +823,7 @@ static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = typhoon_pcihost_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo typhoon_pcihost_info = { +diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c +index 753757e..84cd1ed 100644 +--- a/hw/arm/versatilepb.c ++++ b/hw/arm/versatilepb.c +@@ -387,7 +387,7 @@ static void vpb_sic_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = vpb_sic_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_vpb_sic; + } + +diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c +index 4e03bc9..9186304 100644 +--- a/hw/audio/pcspk.c ++++ b/hw/audio/pcspk.c +@@ -188,7 +188,7 @@ static void pcspk_class_initfn(ObjectClass *klass, void *data) + + ic->init = pcspk_initfn; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pcspk_properties; + } + +diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c +index 9b11cc9..36a7ecb 100644 +--- a/hw/audio/pl041.c ++++ b/hw/audio/pl041.c +@@ -627,7 +627,7 @@ static void pl041_device_class_init(ObjectClass *klass, void *data) + + k->init = pl041_init; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = pl041_device_reset; + dc->vmsd = &vmstate_pl041; + dc->props = pl041_device_properties; +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index e292f4c..1524e09 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2206,7 +2206,7 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = isabus_fdc_init1; + dc->fw_name = "fdc"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = fdctrl_external_reset_isa; + dc->vmsd = &vmstate_isa_fdc; + dc->props = isa_fdc_properties; +diff --git a/hw/display/pl110.c b/hw/display/pl110.c +index b45a7be..173ddf8 100644 +--- a/hw/display/pl110.c ++++ b/hw/display/pl110.c +@@ -482,7 +482,7 @@ static void pl110_class_init(ObjectClass *klass, void *data) + + k->init = pl110_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +@@ -500,7 +500,7 @@ static void pl110_versatile_class_init(ObjectClass *klass, void *data) + + k->init = pl110_versatile_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +@@ -518,7 +518,7 @@ static void pl111_class_init(ObjectClass *klass, void *data) + + k->init = pl111_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c +index 00b66b4..2920780 100644 +--- a/hw/dma/pl080.c ++++ b/hw/dma/pl080.c +@@ -382,7 +382,7 @@ static void pl080_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl080_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl080; + } + +@@ -399,7 +399,7 @@ static void pl081_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl081_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl080; + } + +diff --git a/hw/i2c/smbus_ich9.c b/hw/i2c/smbus_ich9.c +index ca22978..c1ffa34 100644 +--- a/hw/i2c/smbus_ich9.c ++++ b/hw/i2c/smbus_ich9.c +@@ -97,7 +97,7 @@ static void ich9_smb_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_ICH9_6; + k->revision = ICH9_A2_SMB_REVISION; + k->class_id = PCI_CLASS_SERIAL_SMBUS; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_ich9_smbus; + dc->desc = "ICH9 SMBUS Bridge"; + k->init = ich9_smbus_initfn; +diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c +index 98e5ca5..6204939 100644 +--- a/hw/i386/kvm/clock.c ++++ b/hw/i386/kvm/clock.c +@@ -110,7 +110,7 @@ static void kvmclock_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = kvmclock_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &kvmclock_vmsd; + } + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index 655483b..e6405da 100644 +--- a/hw/i386/kvmvapic.c ++++ b/hw/i386/kvmvapic.c +@@ -809,7 +809,7 @@ static void vapic_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = vapic_reset; + dc->vmsd = &vmstate_vapic; + sc->init = vapic_init; +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index d3acbbb..0a8840a 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -538,7 +538,7 @@ static void port92_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = port92_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = port92_reset; + dc->vmsd = &vmstate_port92_isa; + } +diff --git a/hw/ide/piix.c b/hw/ide/piix.c +index 8d4bf2f..e6864b1 100644 +--- a/hw/ide/piix.c ++++ b/hw/ide/piix.c +@@ -249,7 +249,7 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo piix3_ide_info = { +@@ -269,7 +269,7 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->unplug = pci_piix3_xen_ide_unplug; + } + +@@ -292,7 +292,7 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371AB; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo piix4_ide_info = { +diff --git a/hw/ide/via.c b/hw/ide/via.c +index 30dedd8..6ba99c8 100644 +--- a/hw/ide/via.c ++++ b/hw/ide/via.c +@@ -224,7 +224,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) + k->revision = 0x06; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo via_ide_info = { +diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c +index 17a5614..98b8b15 100644 +--- a/hw/input/pckbd.c ++++ b/hw/input/pckbd.c +@@ -514,7 +514,7 @@ static void i8042_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = i8042_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_kbd_isa; + } + +diff --git a/hw/input/vmmouse.c b/hw/input/vmmouse.c +index a610738..c9d5131 100644 +--- a/hw/input/vmmouse.c ++++ b/hw/input/vmmouse.c +@@ -284,7 +284,7 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = vmmouse_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = vmmouse_reset; + dc->vmsd = &vmstate_vmmouse; + dc->props = vmmouse_properties; +diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c +index b03e904..208e7b1 100644 +--- a/hw/intc/apic_common.c ++++ b/hw/intc/apic_common.c +@@ -386,7 +386,7 @@ static void apic_common_class_init(ObjectClass *klass, void *data) + + dc->vmsd = &vmstate_apic_common; + dc->reset = apic_reset_common; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = apic_properties_common; + idc->init = apic_init_common; + } +diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c +index bae6572..243cbf1 100644 +--- a/hw/intc/arm_gic.c ++++ b/hw/intc/arm_gic.c +@@ -702,7 +702,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ARMGICClass *agc = ARM_GIC_CLASS(klass); + +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + agc->parent_realize = dc->realize; + dc->realize = arm_gic_realize; + } +diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c +index 08560f2..26b7756 100644 +--- a/hw/intc/arm_gic_common.c ++++ b/hw/intc/arm_gic_common.c +@@ -156,7 +156,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data) + dc->realize = arm_gic_common_realize; + dc->props = arm_gic_common_properties; + dc->vmsd = &vmstate_gic; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo arm_gic_common_type = { +diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c +index b756456..cb4ce23 100644 +--- a/hw/intc/arm_gic_kvm.c ++++ b/hw/intc/arm_gic_kvm.c +@@ -148,7 +148,7 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) + kgc->parent_reset = dc->reset; + dc->realize = kvm_arm_gic_realize; + dc->reset = kvm_arm_gic_reset; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo kvm_arm_gic_info = { +diff --git a/hw/intc/i8259_common.c b/hw/intc/i8259_common.c +index c2ba6a5..70868a5 100644 +--- a/hw/intc/i8259_common.c ++++ b/hw/intc/i8259_common.c +@@ -139,7 +139,7 @@ static void pic_common_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_pic_common; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pic_properties_common; + ic->init = pic_init_common; + } +diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c +index 5c5bb3c..ce610b7 100644 +--- a/hw/intc/ioapic_common.c ++++ b/hw/intc/ioapic_common.c +@@ -100,7 +100,7 @@ static void ioapic_common_class_init(ObjectClass *klass, void *data) + + sc->init = ioapic_init_common; + dc->vmsd = &vmstate_ioapic_common; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo ioapic_common_type = { +diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c +index 9610673..ff0e5b0 100644 +--- a/hw/intc/pl190.c ++++ b/hw/intc/pl190.c +@@ -269,7 +269,7 @@ static void pl190_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl190_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = pl190_reset; + dc->vmsd = &vmstate_pl190; + } +diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c +index 7860b17..a87a841 100644 +--- a/hw/isa/isa-bus.c ++++ b/hw/isa/isa-bus.c +@@ -217,7 +217,7 @@ static void isabus_bridge_class_init(ObjectClass *klass, void *data) + + k->init = isabus_bridge_init; + dc->fw_name = "isa"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo isabus_bridge_info = { +diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c +index 2760dce..580e9ac 100644 +--- a/hw/isa/lpc_ich9.c ++++ b/hw/isa/lpc_ich9.c +@@ -603,7 +603,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data) + dc->reset = ich9_lpc_reset; + k->init = ich9_lpc_initfn; + dc->vmsd = &vmstate_ich9_lpc; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->config_write = ich9_lpc_config_write; + dc->desc = "ICH9 LPC bridge"; + k->vendor_id = PCI_VENDOR_ID_INTEL; +diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c +index d750413..10bf8ff 100644 +--- a/hw/isa/piix4.c ++++ b/hw/isa/piix4.c +@@ -113,7 +113,7 @@ static void piix4_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0; + k->class_id = PCI_CLASS_BRIDGE_ISA; + dc->desc = "ISA bridge"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_piix4; + } + +diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c +index 79057a6..563e154 100644 +--- a/hw/isa/vt82c686.c ++++ b/hw/isa/vt82c686.c +@@ -468,7 +468,7 @@ static void via_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_BRIDGE_ISA; + k->revision = 0x40; + dc->desc = "ISA bridge"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_via; + } + +diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c +index eb4427d..2b19e34 100644 +--- a/hw/misc/arm_l2x0.c ++++ b/hw/misc/arm_l2x0.c +@@ -174,7 +174,7 @@ static void l2x0_class_init(ObjectClass *klass, void *data) + + k->init = l2x0_priv_init; + dc->vmsd = &vmstate_l2x0; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = l2x0_properties; + dc->reset = l2x0_priv_reset; + } +diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c +index 31e1b1d..af4a8b2 100644 +--- a/hw/misc/pvpanic.c ++++ b/hw/misc/pvpanic.c +@@ -125,7 +125,7 @@ static void pvpanic_isa_class_init(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + + ic->init = pvpanic_isa_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = pvpanic_isa_properties; + } + +diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c +index c146129..ab7adf1 100644 +--- a/hw/misc/vmport.c ++++ b/hw/misc/vmport.c +@@ -156,7 +156,7 @@ static void vmport_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = vmport_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo vmport_info = { +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 1a7e49c..155edd4 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -559,7 +559,7 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = fw_cfg_init1; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = fw_cfg_reset; + dc->vmsd = &vmstate_fw_cfg; + dc->props = fw_cfg_properties; +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index 974150b..b73359e 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -811,7 +811,7 @@ static void bonito_class_init(ObjectClass *klass, void *data) + k->revision = 0x01; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "Host bridge"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_bonito; + } + +@@ -828,7 +828,7 @@ static void bonito_pcihost_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = bonito_pcihost_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo bonito_pcihost_info = { +diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c +index 69344d9..5eb2840 100644 +--- a/hw/pci-host/grackle.c ++++ b/hw/pci-host/grackle.c +@@ -130,7 +130,7 @@ static void grackle_pci_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_MOTOROLA_MPC106; + k->revision = 0x00; + k->class_id = PCI_CLASS_BRIDGE_HOST; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo grackle_pci_info = { +@@ -146,7 +146,7 @@ static void pci_grackle_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = pci_grackle_init_device; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo grackle_pci_host_info = { +diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c +index f9e68c3..b9c2dcf 100644 +--- a/hw/pci-host/piix.c ++++ b/hw/pci-host/piix.c +@@ -564,7 +564,7 @@ static void piix3_class_init(ObjectClass *klass, void *data) + + dc->desc = "ISA bridge"; + dc->vmsd = &vmstate_piix3; +- dc->no_user = 1, ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->no_hotplug = 1; + k->init = piix3_initfn; + k->config_write = piix3_write_config; +@@ -588,7 +588,7 @@ static void piix3_xen_class_init(ObjectClass *klass, void *data) + + dc->desc = "ISA bridge"; + dc->vmsd = &vmstate_piix3; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + k->no_hotplug = 1; + k->init = piix3_initfn; + k->config_write = piix3_write_config_xen; +@@ -618,7 +618,7 @@ static void i440fx_class_init(ObjectClass *klass, void *data) + k->revision = 0x02; + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "Host bridge"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_i440fx; + } + +@@ -636,7 +636,7 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) + + k->init = i440fx_pcihost_initfn; + dc->fw_name = "pci"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo i440fx_pcihost_info = { +diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c +index 8c4e6eb..eec538e 100644 +--- a/hw/pci-host/prep.c ++++ b/hw/pci-host/prep.c +@@ -196,7 +196,7 @@ static void raven_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_BRIDGE_HOST; + dc->desc = "PReP Host Bridge - Motorola Raven"; + dc->vmsd = &vmstate_raven; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo raven_info = { +@@ -213,7 +213,7 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize = raven_pcihost_realizefn; + dc->fw_name = "pci"; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo raven_pcihost_info = { +diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c +index 1405c32..42b6367 100644 +--- a/hw/ppc/spapr_vio.c ++++ b/hw/ppc/spapr_vio.c +@@ -533,7 +533,7 @@ static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = spapr_vio_bridge_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo spapr_vio_bridge_info = { +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index d69adb2..f86a4af 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -181,7 +181,7 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data) + k->init = s390_ipl_init; + dc->props = s390_ipl_properties; + dc->reset = s390_ipl_reset; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo s390_ipl_info = { +diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c +index 207eb82..9078bfb 100644 +--- a/hw/s390x/s390-virtio-bus.c ++++ b/hw/s390x/s390-virtio-bus.c +@@ -679,7 +679,7 @@ static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = s390_virtio_bridge_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo s390_virtio_bridge_info = { +diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c +index de51589..74eb559 100644 +--- a/hw/s390x/virtio-ccw.c ++++ b/hw/s390x/virtio-ccw.c +@@ -1075,7 +1075,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = virtual_css_bridge_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo virtual_css_bridge_info = { +diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c +index 2527296..95e4587 100644 +--- a/hw/sd/pl181.c ++++ b/hw/sd/pl181.c +@@ -497,7 +497,7 @@ static void pl181_class_init(ObjectClass *klass, void *data) + sdc->init = pl181_init; + k->vmsd = &vmstate_pl181; + k->reset = pl181_reset; +- k->no_user = 1; ++ k->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo pl181_info = { +diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c +index 317f5e4..6b088fa 100644 +--- a/hw/timer/arm_mptimer.c ++++ b/hw/timer/arm_mptimer.c +@@ -290,7 +290,7 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data) + sbc->init = arm_mptimer_init; + dc->vmsd = &vmstate_arm_mptimer; + dc->reset = arm_mptimer_reset; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = arm_mptimer_properties; + } + +diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c +index 95dd01d..3f7f457 100644 +--- a/hw/timer/hpet.c ++++ b/hw/timer/hpet.c +@@ -739,7 +739,7 @@ static void hpet_device_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = hpet_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = hpet_reset; + dc->vmsd = &vmstate_hpet; + dc->props = hpet_device_properties; +diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c +index f6f9d26..8f01313 100644 +--- a/hw/timer/i8254_common.c ++++ b/hw/timer/i8254_common.c +@@ -291,7 +291,7 @@ static void pit_common_class_init(ObjectClass *klass, void *data) + + ic->init = pit_init_common; + dc->vmsd = &vmstate_pit_common; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo pit_common_type = { +diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c +index 45753d8..e536bb9 100644 +--- a/hw/timer/m48t59.c ++++ b/hw/timer/m48t59.c +@@ -740,7 +740,7 @@ static void m48t59_isa_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = m48t59_init_isa1; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = m48t59_reset_isa; + dc->props = m48t59_isa_properties; + } +diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c +index 481604d..7a70556 100644 +--- a/hw/timer/mc146818rtc.c ++++ b/hw/timer/mc146818rtc.c +@@ -904,7 +904,7 @@ static void rtc_class_initfn(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = rtc_initfn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_rtc; + dc->props = mc146818rtc_properties; + } +diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c +index 764940b..aa9c5a6 100644 +--- a/hw/timer/pl031.c ++++ b/hw/timer/pl031.c +@@ -246,7 +246,7 @@ static void pl031_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl031_init; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl031; + } + +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index a8618db..44feb54 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -97,7 +97,18 @@ typedef struct DeviceClass { + const char *fw_name; + const char *desc; + Property *props; +- int no_user; ++ ++ /* ++ * Shall we hide this device model from -device / device_add? ++ * All devices should support instantiation with device_add, and ++ * this flag should not exist. But we're not there, yet. Some ++ * devices fail to instantiate with cryptic error messages. ++ * Others instantiate, but don't work. Exposing users to such ++ * behavior would be cruel; this flag serves to protect them. It ++ * should never be set without a comment explaining why it is set. ++ * TODO remove once we're there ++ */ ++ bool cannot_instantiate_with_device_add_yet; + + /* callbacks */ + void (*reset)(DeviceState *dev); +diff --git a/qdev-monitor.c b/qdev-monitor.c +index aa6a261..f54cb21 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -87,7 +87,7 @@ static void qdev_print_devinfo(DeviceClass *dc) + if (dc->desc) { + error_printf(", desc \"%s\"", dc->desc); + } +- if (dc->no_user) { ++ if (dc->cannot_instantiate_with_device_add_yet) { + error_printf(", no-user"); + } + error_printf("\n"); +@@ -127,7 +127,8 @@ static void qdev_print_devinfos(bool show_no_user) + if ((i < DEVICE_CATEGORY_MAX + ? !test_bit(i, dc->categories) + : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX)) +- || (!show_no_user && dc->no_user)) { ++ || (!show_no_user ++ && dc->cannot_instantiate_with_device_add_yet)) { + continue; + } + if (!cat_printed) { +diff --git a/qom/cpu.c b/qom/cpu.c +index b25fbc9..f97e1b8 100644 +--- a/qom/cpu.c ++++ b/qom/cpu.c +@@ -210,7 +210,7 @@ static void cpu_class_init(ObjectClass *klass, void *data) + k->write_elf64_qemunote = cpu_common_write_elf64_qemunote; + k->write_elf64_note = cpu_common_write_elf64_note; + dc->realize = cpu_common_realizefn; +- dc->no_user = 1; ++ dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo cpu_type_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-qdev-monitor-Group-device_add-help-and-info-qdm-by-c.patch b/SOURCES/kvm-qdev-monitor-Group-device_add-help-and-info-qdm-by-c.patch new file mode 100644 index 0000000..c48605d --- /dev/null +++ b/SOURCES/kvm-qdev-monitor-Group-device_add-help-and-info-qdm-by-c.patch @@ -0,0 +1,142 @@ +From 4729118339de86313e09cb20414ba699510a80cc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:11 +0100 +Subject: [PATCH 35/81] qdev-monitor: Group "device_add help" and "info qdm" by category + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-7-git-send-email-kwolf@redhat.com> +Patchwork-id: 55532 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 06/17] qdev-monitor: Group "device_add help" and "info qdm" by category +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Output is a long, unsorted list. Not very helpful. Print one list +per device category instead, with a header line identifying the +category, plus a list of uncategorized devices. Print each list in +case-insenitive alphabetical order. + +Devices with multiple categories are listed multiple times. + +Signed-off-by: Markus Armbruster +Reviewed-by: Marcel Apfelbaum +Message-id: 1381410021-1538-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit a3400aeede46c6c30b6fefb20fc90a43f1f6e7b2) +Signed-off-by: Kevin Wolf +--- + qdev-monitor.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 53 insertions(+), 14 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qdev-monitor.c | 67 ++++++++++++++++++++++++++++++++++++++++++++----------- + 1 files changed, 53 insertions(+), 14 deletions(-) + +diff --git a/qdev-monitor.c b/qdev-monitor.c +index e54dbc2..aa6a261 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -75,18 +75,9 @@ static bool qdev_class_has_alias(DeviceClass *dc) + return (qdev_class_get_alias(dc) != NULL); + } + +-static void qdev_print_devinfo(ObjectClass *klass, void *opaque) ++static void qdev_print_devinfo(DeviceClass *dc) + { +- DeviceClass *dc; +- bool *show_no_user = opaque; +- +- dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); +- +- if (!dc || (show_no_user && !*show_no_user && dc->no_user)) { +- return; +- } +- +- error_printf("name \"%s\"", object_class_get_name(klass)); ++ error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc))); + if (dc->bus_type) { + error_printf(", bus %s", dc->bus_type); + } +@@ -102,6 +93,55 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque) + error_printf("\n"); + } + ++static gint devinfo_cmp(gconstpointer a, gconstpointer b) ++{ ++ return strcasecmp(object_class_get_name((ObjectClass *)a), ++ object_class_get_name((ObjectClass *)b)); ++} ++ ++static void qdev_print_devinfos(bool show_no_user) ++{ ++ static const char *cat_name[DEVICE_CATEGORY_MAX + 1] = { ++ [DEVICE_CATEGORY_BRIDGE] = "Controller/Bridge/Hub", ++ [DEVICE_CATEGORY_USB] = "USB", ++ [DEVICE_CATEGORY_STORAGE] = "Storage", ++ [DEVICE_CATEGORY_NETWORK] = "Network", ++ [DEVICE_CATEGORY_INPUT] = "Input", ++ [DEVICE_CATEGORY_DISPLAY] = "Display", ++ [DEVICE_CATEGORY_SOUND] = "Sound", ++ [DEVICE_CATEGORY_MISC] = "Misc", ++ [DEVICE_CATEGORY_MAX] = "Uncategorized", ++ }; ++ GSList *list, *elt; ++ int i; ++ bool cat_printed; ++ ++ list = g_slist_sort(object_class_get_list(TYPE_DEVICE, false), ++ devinfo_cmp); ++ ++ for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) { ++ cat_printed = false; ++ for (elt = list; elt; elt = elt->next) { ++ DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data, ++ TYPE_DEVICE); ++ if ((i < DEVICE_CATEGORY_MAX ++ ? !test_bit(i, dc->categories) ++ : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX)) ++ || (!show_no_user && dc->no_user)) { ++ continue; ++ } ++ if (!cat_printed) { ++ error_printf("%s%s devices:\n", i ? "\n" : "", ++ cat_name[i]); ++ cat_printed = true; ++ } ++ qdev_print_devinfo(dc); ++ } ++ } ++ ++ g_slist_free(list); ++} ++ + static int set_property(const char *name, const char *value, void *opaque) + { + DeviceState *dev = opaque; +@@ -147,8 +187,7 @@ int qdev_device_help(QemuOpts *opts) + + driver = qemu_opt_get(opts, "driver"); + if (driver && is_help_option(driver)) { +- bool show_no_user = false; +- object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user); ++ qdev_print_devinfos(false); + return 1; + } + +@@ -587,7 +626,7 @@ void do_info_qtree(Monitor *mon, const QDict *qdict) + + void do_info_qdm(Monitor *mon, const QDict *qdict) + { +- object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL); ++ qdev_print_devinfos(true); + } + + int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data) +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-add-chardev-mux-support.patch b/SOURCES/kvm-qemu-char-add-chardev-mux-support.patch new file mode 100644 index 0000000..94c299c --- /dev/null +++ b/SOURCES/kvm-qemu-char-add-chardev-mux-support.patch @@ -0,0 +1,79 @@ +From e7980021a52658198f04024cb762f09aac607e97 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:20 +0200 +Subject: [PATCH 13/18] qemu-char: add -chardev mux support + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-13-git-send-email-kraxel@redhat.com> +Patchwork-id: 54857 +O-Subject: [RHEL-7 qemu-kvm PATCH 12/15] qemu-char: add -chardev mux support +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Allow to explicitly create mux chardevs on the command line, +like you can using QMP. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit bb6fb7c0857aeda7982ac14460328edf3c29cfc8) + +Conflicts: + qemu-char.c +--- + qemu-char.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 18 ++++++++++++++++++ + 1 files changed, 18 insertions(+), 0 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 145fd30..fc1b21a 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3142,6 +3142,19 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend, + } + } + ++static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, ++ Error **errp) ++{ ++ const char *chardev = qemu_opt_get(opts, "chardev"); ++ ++ if (chardev == NULL) { ++ error_setg(errp, "chardev: mux: no chardev given"); ++ return; ++ } ++ backend->mux = g_new0(ChardevMux, 1); ++ backend->mux->chardev = g_strdup(chardev); ++} ++ + typedef struct CharDriver { + const char *name; + /* old, pre qapi */ +@@ -3509,6 +3522,9 @@ QemuOptsList qemu_chardev_opts = { + },{ + .name = "size", + .type = QEMU_OPT_SIZE, ++ },{ ++ .name = "chardev", ++ .type = QEMU_OPT_STRING, + }, + { /* end of list */ } + }, +@@ -3800,6 +3816,8 @@ static void register_types(void) + register_char_driver_qapi("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL); + register_char_driver_qapi("pipe", CHARDEV_BACKEND_KIND_PIPE, + qemu_chr_parse_pipe); ++ register_char_driver_qapi("mux", CHARDEV_BACKEND_KIND_MUX, ++ qemu_chr_parse_mux); + /* Bug-compatibility: */ + register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY, + qemu_chr_parse_ringbuf); +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-check-optional-fields-using-has_.patch b/SOURCES/kvm-qemu-char-check-optional-fields-using-has_.patch new file mode 100644 index 0000000..19f6714 --- /dev/null +++ b/SOURCES/kvm-qemu-char-check-optional-fields-using-has_.patch @@ -0,0 +1,52 @@ +From 99421ce09cafb7fccd0d3db0144210ba16f40718 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:12 +0200 +Subject: [PATCH 05/18] qemu-char: check optional fields using has_* + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-5-git-send-email-kraxel@redhat.com> +Patchwork-id: 54850 +O-Subject: [RHEL-7 qemu-kvm PATCH 04/15] qemu-char: check optional fields using has_* +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit e859eda58501cd20a2e6988fb4acc1756bc4d278) +--- + qemu-char.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 660d758..ddc3dca 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3521,7 +3521,7 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp) + { + HANDLE out; + +- if (file->in) { ++ if (file->has_in) { + error_setg(errp, "input file not supported"); + return NULL; + } +@@ -3572,7 +3572,7 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp) + return NULL; + } + +- if (file->in) { ++ if (file->has_in) { + flags = O_RDONLY; + in = qmp_chardev_open_file_source(file->in, flags, errp); + if (error_is_set(errp)) { +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-don-t-leak-opts-on-error.patch b/SOURCES/kvm-qemu-char-don-t-leak-opts-on-error.patch new file mode 100644 index 0000000..8d99ad7 --- /dev/null +++ b/SOURCES/kvm-qemu-char-don-t-leak-opts-on-error.patch @@ -0,0 +1,43 @@ +From 9a03ecd49c63fdad85a073834b29748a7b12824e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:17 +0200 +Subject: [PATCH 10/18] qemu-char: don't leak opts on error + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-10-git-send-email-kraxel@redhat.com> +Patchwork-id: 54852 +O-Subject: [RHEL-7 qemu-kvm PATCH 09/15] qemu-char: don't leak opts on error +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit e668287d4413395be1a0f9ef292bb6d0c1006e29) +--- + qemu-char.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index 62fafb0..43bd5e2 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3205,7 +3205,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, + if (i == NULL) { + error_setg(errp, "chardev: backend \"%s\" not found", + qemu_opt_get(opts, "backend")); +- return NULL; ++ goto err; + } + + if (!cd->open) { +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-fix-documentation-for-telnet-wait-socket-f.patch b/SOURCES/kvm-qemu-char-fix-documentation-for-telnet-wait-socket-f.patch new file mode 100644 index 0000000..24a1a26 --- /dev/null +++ b/SOURCES/kvm-qemu-char-fix-documentation-for-telnet-wait-socket-f.patch @@ -0,0 +1,49 @@ +From e93fe39c1553da8bc81a08e4ab31698a24395a51 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:16 +0200 +Subject: [PATCH 09/18] qemu-char: fix documentation for telnet+wait socket flags + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-9-git-send-email-kraxel@redhat.com> +Patchwork-id: 54854 +O-Subject: [RHEL-7 qemu-kvm PATCH 08/15] qemu-char: fix documentation for telnet+wait socket flags +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit ef993ba7bc631b57f9ea70a7f6fc8c0fcbdfa19d) +--- + qapi-schema.json | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qapi-schema.json | 7 ++++--- + 1 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/qapi-schema.json b/qapi-schema.json +index ffe0ed1..780c6fe 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -3213,10 +3213,11 @@ + # @addr: socket address to listen on (server=true) + # or connect to (server=false) + # @server: #optional create server socket (default: true) +-# @wait: #optional wait for connect (not used for server +-# sockets, default: false) ++# @wait: #optional wait for incoming connection on server ++# sockets (default: false). + # @nodelay: #optional set TCP_NODELAY socket option (default: false) +-# @telnet: #optional enable telnet protocol (default: false) ++# @telnet: #optional enable telnet protocol on server ++# sockets (default: false) + # + # Since: 1.4 + ## +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-minor-mux-chardev-fixes.patch b/SOURCES/kvm-qemu-char-minor-mux-chardev-fixes.patch new file mode 100644 index 0000000..af204c8 --- /dev/null +++ b/SOURCES/kvm-qemu-char-minor-mux-chardev-fixes.patch @@ -0,0 +1,68 @@ +From c4a5b67ffac094aa1653de8e9369585b0bc4ee46 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:19 +0200 +Subject: [PATCH 12/18] qemu-char: minor mux chardev fixes + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-12-git-send-email-kraxel@redhat.com> +Patchwork-id: 54861 +O-Subject: [RHEL-7 qemu-kvm PATCH 11/15] qemu-char: minor mux chardev fixes +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +mux failure path has a memory leak. creating a mux chardev can't +fail though, so just assert() that instead of fixing an error path +which never ever runs anyway ... + +Also fix bid being leaked while being at it. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit dc2c4eca89ec5ee7b7a4c2563c991a14a7c5ee84) +--- + qemu-char.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 7 +++---- + 1 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index b41bda4..145fd30 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3213,7 +3213,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, + ChardevBackend *backend = g_new0(ChardevBackend, 1); + ChardevReturn *ret = NULL; + const char *id = qemu_opts_id(opts); +- const char *bid = NULL; ++ char *bid = NULL; + + if (qemu_opt_get_bool(opts, "mux", 0)) { + bid = g_strdup_printf("%s-base", id); +@@ -3240,9 +3240,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, + backend->kind = CHARDEV_BACKEND_KIND_MUX; + backend->mux->chardev = g_strdup(bid); + ret = qmp_chardev_add(id, backend, errp); +- if (error_is_set(errp)) { +- goto qapi_out; +- } ++ assert(!error_is_set(errp)); + } + + chr = qemu_chr_find(id); +@@ -3251,6 +3249,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, + qapi_out: + qapi_free_ChardevBackend(backend); + qapi_free_ChardevReturn(ret); ++ g_free(bid); + return chr; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-print-notification-to-stderr.patch b/SOURCES/kvm-qemu-char-print-notification-to-stderr.patch new file mode 100644 index 0000000..63d5b02 --- /dev/null +++ b/SOURCES/kvm-qemu-char-print-notification-to-stderr.patch @@ -0,0 +1,45 @@ +From 5617925ceaeae6855991e5397e015e3230548605 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:15 +0200 +Subject: [PATCH 08/18] qemu-char: print notification to stderr + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-8-git-send-email-kraxel@redhat.com> +Patchwork-id: 54851 +O-Subject: [RHEL-7 qemu-kvm PATCH 07/15] qemu-char: print notification to stderr +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit fdca2124adc293f84f2b7aaf0df43faa6b6bf420) +--- + qemu-char.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index f783a87..62fafb0 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -2686,8 +2686,8 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, + } + + if (is_listen && is_waitconnect) { +- printf("QEMU waiting for connection on: %s\n", +- chr->filename); ++ fprintf(stderr, "QEMU waiting for connection on: %s\n", ++ chr->filename); + tcp_chr_accept(s->listen_chan, G_IO_IN, chr); + qemu_set_nonblock(s->listen_fd); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-report-udp-backend-errors.patch b/SOURCES/kvm-qemu-char-report-udp-backend-errors.patch new file mode 100644 index 0000000..5c907c9 --- /dev/null +++ b/SOURCES/kvm-qemu-char-report-udp-backend-errors.patch @@ -0,0 +1,43 @@ +From ecf98a5629d252b6fb2c9aa5baa9282828f3243b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:21 +0200 +Subject: [PATCH 14/18] qemu-char: report udp backend errors + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-14-git-send-email-kraxel@redhat.com> +Patchwork-id: 54855 +O-Subject: [RHEL-7 qemu-kvm PATCH 13/15] qemu-char: report udp backend errors +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit 58a3714c529b1b97ee078ea25b58f731aabcbfff) +--- + qemu-char.c | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index fc1b21a..bacc7b7 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -2280,6 +2280,8 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts) + + fd = inet_dgram_opts(opts, &local_err); + if (fd < 0) { ++ qerror_report_err(local_err); ++ error_free(local_err); + return NULL; + } + return qemu_chr_open_udp_fd(fd); +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-use-ChardevBackendKind-in-CharDriver.patch b/SOURCES/kvm-qemu-char-use-ChardevBackendKind-in-CharDriver.patch new file mode 100644 index 0000000..97c449b --- /dev/null +++ b/SOURCES/kvm-qemu-char-use-ChardevBackendKind-in-CharDriver.patch @@ -0,0 +1,67 @@ +From 81a8d16533d8fa17be434d87b5ba097387b12b59 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:18 +0200 +Subject: [PATCH 11/18] qemu-char: use ChardevBackendKind in CharDriver + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-11-git-send-email-kraxel@redhat.com> +Patchwork-id: 54864 +O-Subject: [RHEL-7 qemu-kvm PATCH 10/15] qemu-char: use ChardevBackendKind in CharDriver +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit 99aec0123ce5ba307dc357c5bf1e0f22d2be0931) +--- + include/sysemu/char.h | 2 +- + qemu-char.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/sysemu/char.h | 2 +- + qemu-char.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/include/sysemu/char.h b/include/sysemu/char.h +index f0ed280..ad101d9 100644 +--- a/include/sysemu/char.h ++++ b/include/sysemu/char.h +@@ -283,7 +283,7 @@ CharDriverState *qemu_chr_find(const char *name); + QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); + + void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *)); +-void register_char_driver_qapi(const char *name, int kind, ++void register_char_driver_qapi(const char *name, ChardevBackendKind kind, + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp)); + + /* add an eventfd to the qemu devices that are polled */ +diff --git a/qemu-char.c b/qemu-char.c +index 43bd5e2..b41bda4 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -3147,7 +3147,7 @@ typedef struct CharDriver { + /* old, pre qapi */ + CharDriverState *(*open)(QemuOpts *opts); + /* new, qapi-based */ +- int kind; ++ ChardevBackendKind kind; + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); + } CharDriver; + +@@ -3164,7 +3164,7 @@ void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *) + backends = g_slist_append(backends, s); + } + +-void register_char_driver_qapi(const char *name, int kind, ++void register_char_driver_qapi(const char *name, ChardevBackendKind kind, + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp)) + { + CharDriver *s; +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-char-use-more-specific-error_setg_-variants.patch b/SOURCES/kvm-qemu-char-use-more-specific-error_setg_-variants.patch new file mode 100644 index 0000000..0eb3dbd --- /dev/null +++ b/SOURCES/kvm-qemu-char-use-more-specific-error_setg_-variants.patch @@ -0,0 +1,52 @@ +From 54cee6b36249a4486cdef86fe107fd2fbf8885fd Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:14 +0200 +Subject: [PATCH 07/18] qemu-char: use more specific error_setg_* variants + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-7-git-send-email-kraxel@redhat.com> +Patchwork-id: 54859 +O-Subject: [RHEL-7 qemu-kvm PATCH 06/15] qemu-char: use more specific error_setg_* variants +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit 20c397607cb54905f452921259b4baa9c8a1d008) +--- + qemu-char.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-char.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qemu-char.c b/qemu-char.c +index ddc3dca..f783a87 100644 +--- a/qemu-char.c ++++ b/qemu-char.c +@@ -2624,7 +2624,7 @@ static CharDriverState *qemu_chr_open_socket_fd(int fd, bool do_nodelay, + + memset(&ss, 0, ss_len); + if (getsockname(fd, (struct sockaddr *) &ss, &ss_len) != 0) { +- error_setg(errp, "getsockname: %s", strerror(errno)); ++ error_setg_errno(errp, errno, "getsockname"); + return NULL; + } + +@@ -3557,7 +3557,7 @@ static int qmp_chardev_open_file_source(char *src, int flags, + + TFR(fd = qemu_open(src, flags, 0666)); + if (fd == -1) { +- error_setg(errp, "open %s: %s", src, strerror(errno)); ++ error_setg_file_open(errp, errno, src); + } + return fd; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-ga-execute-fsfreeze-freeze-in-reverse-order-of-.patch b/SOURCES/kvm-qemu-ga-execute-fsfreeze-freeze-in-reverse-order-of-.patch new file mode 100644 index 0000000..bcee4b4 --- /dev/null +++ b/SOURCES/kvm-qemu-ga-execute-fsfreeze-freeze-in-reverse-order-of-.patch @@ -0,0 +1,71 @@ +From 80fc609da0904d6b8f21ef017808622567ed91b5 Mon Sep 17 00:00:00 2001 +Message-Id: <80fc609da0904d6b8f21ef017808622567ed91b5.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Tomoki Sekiyama +Date: Tue, 15 Oct 2013 21:40:57 +0200 +Subject: [PATCH 11/14] qemu-ga: execute fsfreeze-freeze in reverse order of + mounts + +RH-Author: Tomoki Sekiyama +Message-id: <1381873257-2800-1-git-send-email-tsekiyam@redhat.com> +Patchwork-id: 54955 +O-Subject: [RHEL 7.0 qemu-kvm PATCH] qemu-ga: execute fsfreeze-freeze in reverse order of mounts +Bugzilla: 1019352 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz +RH-Acked-by: Luiz Capitulino + +From: Tomoki Sekiyama + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1019352 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6420515 + +Currently, fsfreeze-freeze may cause deadlock if a guest has loopback mounts +of image files in its disk; e.g.: + + # mount | grep ^/ + /dev/vda1 / type ext4 (rw,noatime,seclabel,data=ordered) + /tmp/disk.img on /mnt type ext4 (rw,relatime,seclabel) + +To avoid the deadlock, this freezes filesystems in reverse order of mounts. + +Signed-off-by: Tomoki Sekiyama +Reviewed-by: Eric Blake +*fix up commit msg +Signed-off-by: Michael Roth +(cherry picked from commit e5d9adbdab972a2172815c1174aed3fabcc448f1) +--- + qga/commands-posix.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Michal Novotny +--- + qga/commands-posix.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/qga/commands-posix.c b/qga/commands-posix.c +index e199738..f453132 100644 +--- a/qga/commands-posix.c ++++ b/qga/commands-posix.c +@@ -566,7 +566,7 @@ typedef struct FsMount { + QTAILQ_ENTRY(FsMount) next; + } FsMount; + +-typedef QTAILQ_HEAD(, FsMount) FsMountList; ++typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList; + + static void free_fs_mount_list(FsMountList *mounts) + { +@@ -728,7 +728,7 @@ int64_t qmp_guest_fsfreeze_freeze(Error **err) + /* cannot risk guest agent blocking itself on a write in this state */ + ga_set_frozen(ga_state); + +- QTAILQ_FOREACH(mount, &mounts, next) { ++ QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) { + fd = qemu_open(mount->dirname, O_RDONLY); + if (fd == -1) { + error_setg_errno(err, errno, "failed to open %s", mount->dirname); +-- +1.7.11.7 + diff --git a/SOURCES/kvm-qemu-help-Sort-devices-by-logical-functionality.patch b/SOURCES/kvm-qemu-help-Sort-devices-by-logical-functionality.patch new file mode 100644 index 0000000..cf27f8c --- /dev/null +++ b/SOURCES/kvm-qemu-help-Sort-devices-by-logical-functionality.patch @@ -0,0 +1,181 @@ +From 28b2998fb1285514c2c342d174a36330734cd79c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:08 +0100 +Subject: [PATCH 32/81] qemu-help: Sort devices by logical functionality + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-4-git-send-email-kwolf@redhat.com> +Patchwork-id: 55529 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 03/17] qemu-help: Sort devices by logical functionality +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Marcel Apfelbaum + +Categorize devices that appear as output to "-device ?" command +by logical functionality. Sort the devices by logical categories +before showing them to user. + +The sort is done by functionality rather than alphabetical. + +Signed-off-by: Marcel Apfelbaum +Message-id: 1375107465-25767-3-git-send-email-marcel.a@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 3d1237fb2ab4edb926c717767bb5e31d6053a7c5) +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + include/hw/qdev-core.h | 29 +++++++++++++++++++++++++++++ + qdev-monitor.c | 48 +++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 68 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/hw/qdev-core.h | 29 +++++++++++++++++++++++++++++ + qdev-monitor.c | 48 +++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 68 insertions(+), 9 deletions(-) + +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 9d995bf..18596e9 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -18,6 +18,34 @@ enum { + #define DEVICE_CLASS(klass) OBJECT_CLASS_CHECK(DeviceClass, (klass), TYPE_DEVICE) + #define DEVICE_GET_CLASS(obj) OBJECT_GET_CLASS(DeviceClass, (obj), TYPE_DEVICE) + ++typedef enum DeviceCategory { ++ DEVICE_CATEGORY_BRIDGE, ++ DEVICE_CATEGORY_USB, ++ DEVICE_CATEGORY_STORAGE, ++ DEVICE_CATEGORY_NETWORK, ++ DEVICE_CATEGORY_INPUT, ++ DEVICE_CATEGORY_DISPLAY, ++ DEVICE_CATEGORY_SOUND, ++ DEVICE_CATEGORY_MISC, ++ DEVICE_CATEGORY_MAX ++} DeviceCategory; ++ ++static inline const char *qdev_category_get_name(DeviceCategory category) ++{ ++ static const char *category_names[DEVICE_CATEGORY_MAX] = { ++ [DEVICE_CATEGORY_BRIDGE] = "Controller/Bridge/Hub", ++ [DEVICE_CATEGORY_USB] = "USB", ++ [DEVICE_CATEGORY_STORAGE] = "Storage", ++ [DEVICE_CATEGORY_NETWORK] = "Network", ++ [DEVICE_CATEGORY_INPUT] = "Input", ++ [DEVICE_CATEGORY_DISPLAY] = "Display", ++ [DEVICE_CATEGORY_SOUND] = "Sound", ++ [DEVICE_CATEGORY_MISC] = "Misc", ++ }; ++ ++ return category_names[category]; ++}; ++ + typedef int (*qdev_initfn)(DeviceState *dev); + typedef int (*qdev_event)(DeviceState *dev); + typedef void (*qdev_resetfn)(DeviceState *dev); +@@ -81,6 +109,7 @@ typedef struct DeviceClass { + ObjectClass parent_class; + /*< public >*/ + ++ DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX); + const char *fw_name; + const char *desc; + Property *props; +diff --git a/qdev-monitor.c b/qdev-monitor.c +index e54dbc2..230a8df 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -75,24 +75,27 @@ static bool qdev_class_has_alias(DeviceClass *dc) + return (qdev_class_get_alias(dc) != NULL); + } + +-static void qdev_print_devinfo(ObjectClass *klass, void *opaque) ++static void qdev_print_class_devinfo(DeviceClass *dc) + { +- DeviceClass *dc; +- bool *show_no_user = opaque; +- +- dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); ++ DeviceCategory category; + +- if (!dc || (show_no_user && !*show_no_user && dc->no_user)) { ++ if (!dc) { + return; + } + +- error_printf("name \"%s\"", object_class_get_name(klass)); ++ error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc))); + if (dc->bus_type) { + error_printf(", bus %s", dc->bus_type); + } + if (qdev_class_has_alias(dc)) { + error_printf(", alias \"%s\"", qdev_class_get_alias(dc)); + } ++ error_printf(", categories"); ++ for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) { ++ if (test_bit(category, dc->categories)) { ++ error_printf(" \"%s\"", qdev_category_get_name(category)); ++ } ++ } + if (dc->desc) { + error_printf(", desc \"%s\"", dc->desc); + } +@@ -102,6 +105,15 @@ static void qdev_print_devinfo(ObjectClass *klass, void *opaque) + error_printf("\n"); + } + ++static void qdev_print_devinfo(ObjectClass *klass, void *opaque) ++{ ++ DeviceClass *dc; ++ ++ dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE); ++ ++ qdev_print_class_devinfo(dc); ++} ++ + static int set_property(const char *name, const char *value, void *opaque) + { + DeviceState *dev = opaque; +@@ -139,6 +151,21 @@ static const char *find_typename_by_alias(const char *alias) + return NULL; + } + ++static void qdev_print_category_devices(DeviceCategory category) ++{ ++ DeviceClass *dc; ++ GSList *list, *curr; ++ ++ list = object_class_get_list(TYPE_DEVICE, false); ++ for (curr = list; curr; curr = g_slist_next(curr)) { ++ dc = (DeviceClass *)object_class_dynamic_cast(curr->data, TYPE_DEVICE); ++ if (!dc->no_user && test_bit(category, dc->categories)) { ++ qdev_print_class_devinfo(dc); ++ } ++ } ++ g_slist_free(list); ++} ++ + int qdev_device_help(QemuOpts *opts) + { + const char *driver; +@@ -147,8 +174,11 @@ int qdev_device_help(QemuOpts *opts) + + driver = qemu_opt_get(opts, "driver"); + if (driver && is_help_option(driver)) { +- bool show_no_user = false; +- object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user); ++ DeviceCategory category; ++ for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) { ++ qdev_print_category_devices(category); ++ } ++ + return 1; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-img-Error-out-for-excess-arguments.patch b/SOURCES/kvm-qemu-img-Error-out-for-excess-arguments.patch new file mode 100644 index 0000000..00f305b --- /dev/null +++ b/SOURCES/kvm-qemu-img-Error-out-for-excess-arguments.patch @@ -0,0 +1,108 @@ +From 00e5b1ffe79264929ea0dab871e5e797ab85497f Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 19 Aug 2013 11:09:45 +0200 +Subject: qemu-img: Error out for excess arguments + +RH-Author: Max Reitz +Message-id: <1376910585-8875-1-git-send-email-mreitz@redhat.com> +Patchwork-id: 53597 +O-Subject: [RHEL-7 qemu-kvm PATCH] qemu-img: Error out for excess arguments +Bugzilla: 992935 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi + +From: Kevin Wolf + +Don't silently ignore excess arguments at the end of the command line, +but error out instead. This can catch typos like 'resize test.img + 1G', +which doesn't increase the image size by 1G as intended, but truncates +the image to 1G. Even for less dangerous commands, the old behaviour is +confusing. + +Signed-off-by: Kevin Wolf +Reviewed-by: Laszlo Ersek +Reviewed-by: Stefan Hajnoczi +(cherry picked from commit fc11eb26cee7e3621645dd40cd9de944201f590b) +Signed-off-by: Max Reitz + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=992935 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6181030 + +diff --git a/qemu-img.c b/qemu-img.c +index cd096a1..c20ff66 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -393,6 +393,9 @@ static int img_create(int argc, char **argv) + } + img_size = (uint64_t)sval; + } ++ if (optind != argc) { ++ help(); ++ } + + if (options && is_help_option(options)) { + return print_block_option_help(filename, fmt); +@@ -570,7 +573,7 @@ static int img_check(int argc, char **argv) + break; + } + } +- if (optind >= argc) { ++ if (optind != argc - 1) { + help(); + } + filename = argv[optind++]; +@@ -681,7 +684,7 @@ static int img_commit(int argc, char **argv) + break; + } + } +- if (optind >= argc) { ++ if (optind != argc - 1) { + help(); + } + filename = argv[optind++]; +@@ -927,7 +930,7 @@ static int img_compare(int argc, char **argv) + } + + +- if (optind > argc - 2) { ++ if (optind != argc - 2) { + help(); + } + filename1 = argv[optind++]; +@@ -1882,7 +1885,7 @@ static int img_info(int argc, char **argv) + break; + } + } +- if (optind >= argc) { ++ if (optind != argc - 1) { + help(); + } + filename = argv[optind++]; +@@ -1983,7 +1986,7 @@ static int img_snapshot(int argc, char **argv) + } + } + +- if (optind >= argc) { ++ if (optind != argc - 1) { + help(); + } + filename = argv[optind++]; +@@ -2094,7 +2097,7 @@ static int img_rebase(int argc, char **argv) + progress = 0; + } + +- if ((optind >= argc) || (!unsafe && !out_baseimg)) { ++ if ((optind != argc - 1) || (!unsafe && !out_baseimg)) { + help(); + } + filename = argv[optind++]; +@@ -2373,7 +2376,7 @@ static int img_resize(int argc, char **argv) + break; + } + } +- if (optind >= argc) { ++ if (optind != argc - 1) { + help(); + } + filename = argv[optind++]; diff --git a/SOURCES/kvm-qemu-img-add-a-map-subcommand.patch b/SOURCES/kvm-qemu-img-add-a-map-subcommand.patch new file mode 100644 index 0000000..5eb997e --- /dev/null +++ b/SOURCES/kvm-qemu-img-add-a-map-subcommand.patch @@ -0,0 +1,253 @@ +From 43c680e82e94061bf1b522466054730d8f3d8c22 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:42 +0200 +Subject: [PATCH 17/81] qemu-img: add a "map" subcommand + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-18-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55000 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 17/26] qemu-img: add a "map" subcommand +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +This command dumps the metadata of an entire chain, in either tabular or JSON +format. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4c93a13b5daf9bd5fca1a547661b0fb9a2f0ca52) +--- + qemu-img-cmds.hx | 6 ++ + qemu-img.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 198 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + qemu-img-cmds.hx | 6 ++ + qemu-img.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 198 insertions(+), 0 deletions(-) + +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 4ca7e95..c97a1f4 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -45,6 +45,12 @@ STEXI + @item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} + ETEXI + ++DEF("map", img_map, ++ "map [-f fmt] [--output=ofmt] filename") ++STEXI ++@item map [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} ++ETEXI ++ + DEF("snapshot", img_snapshot, + "snapshot [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") + STEXI +diff --git a/qemu-img.c b/qemu-img.c +index a9aabd5..e58c052 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1919,6 +1919,198 @@ static int img_info(int argc, char **argv) + return 0; + } + ++ ++typedef struct MapEntry { ++ int flags; ++ int depth; ++ int64_t start; ++ int64_t length; ++ int64_t offset; ++ BlockDriverState *bs; ++} MapEntry; ++ ++static void dump_map_entry(OutputFormat output_format, MapEntry *e, ++ MapEntry *next) ++{ ++ switch (output_format) { ++ case OFORMAT_HUMAN: ++ if ((e->flags & BDRV_BLOCK_DATA) && ++ !(e->flags & BDRV_BLOCK_OFFSET_VALID)) { ++ error_report("File contains external, encrypted or compressed clusters."); ++ exit(1); ++ } ++ if ((e->flags & (BDRV_BLOCK_DATA|BDRV_BLOCK_ZERO)) == BDRV_BLOCK_DATA) { ++ printf("%#-16"PRIx64"%#-16"PRIx64"%#-16"PRIx64"%s\n", ++ e->start, e->length, e->offset, e->bs->filename); ++ } ++ /* This format ignores the distinction between 0, ZERO and ZERO|DATA. ++ * Modify the flags here to allow more coalescing. ++ */ ++ if (next && ++ (next->flags & (BDRV_BLOCK_DATA|BDRV_BLOCK_ZERO)) != BDRV_BLOCK_DATA) { ++ next->flags &= ~BDRV_BLOCK_DATA; ++ next->flags |= BDRV_BLOCK_ZERO; ++ } ++ break; ++ case OFORMAT_JSON: ++ printf("%s{ \"start\": %"PRId64", \"length\": %"PRId64", \"depth\": %d," ++ " \"zero\": %s, \"data\": %s", ++ (e->start == 0 ? "[" : ",\n"), ++ e->start, e->length, e->depth, ++ (e->flags & BDRV_BLOCK_ZERO) ? "true" : "false", ++ (e->flags & BDRV_BLOCK_DATA) ? "true" : "false"); ++ if (e->flags & BDRV_BLOCK_OFFSET_VALID) { ++ printf(", 'offset': %"PRId64"", e->offset); ++ } ++ putchar('}'); ++ ++ if (!next) { ++ printf("]\n"); ++ } ++ break; ++ } ++} ++ ++static int get_block_status(BlockDriverState *bs, int64_t sector_num, ++ int nb_sectors, MapEntry *e) ++{ ++ int64_t ret; ++ int depth; ++ ++ /* As an optimization, we could cache the current range of unallocated ++ * clusters in each file of the chain, and avoid querying the same ++ * range repeatedly. ++ */ ++ ++ depth = 0; ++ for (;;) { ++ ret = bdrv_get_block_status(bs, sector_num, nb_sectors, &nb_sectors); ++ if (ret < 0) { ++ return ret; ++ } ++ assert(nb_sectors); ++ if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) { ++ break; ++ } ++ bs = bs->backing_hd; ++ if (bs == NULL) { ++ ret = 0; ++ break; ++ } ++ ++ depth++; ++ } ++ ++ e->start = sector_num * BDRV_SECTOR_SIZE; ++ e->length = nb_sectors * BDRV_SECTOR_SIZE; ++ e->flags = ret & ~BDRV_BLOCK_OFFSET_MASK; ++ e->offset = ret & BDRV_BLOCK_OFFSET_MASK; ++ e->depth = depth; ++ e->bs = bs; ++ return 0; ++} ++ ++static int img_map(int argc, char **argv) ++{ ++ int c; ++ OutputFormat output_format = OFORMAT_HUMAN; ++ BlockDriverState *bs; ++ const char *filename, *fmt, *output; ++ int64_t length; ++ MapEntry curr = { .length = 0 }, next; ++ int ret = 0; ++ ++ fmt = NULL; ++ output = NULL; ++ for (;;) { ++ int option_index = 0; ++ static const struct option long_options[] = { ++ {"help", no_argument, 0, 'h'}, ++ {"format", required_argument, 0, 'f'}, ++ {"output", required_argument, 0, OPTION_OUTPUT}, ++ {0, 0, 0, 0} ++ }; ++ c = getopt_long(argc, argv, "f:h", ++ long_options, &option_index); ++ if (c == -1) { ++ break; ++ } ++ switch (c) { ++ case '?': ++ case 'h': ++ help(); ++ break; ++ case 'f': ++ fmt = optarg; ++ break; ++ case OPTION_OUTPUT: ++ output = optarg; ++ break; ++ } ++ } ++ if (optind >= argc) { ++ help(); ++ } ++ filename = argv[optind++]; ++ ++ if (output && !strcmp(output, "json")) { ++ output_format = OFORMAT_JSON; ++ } else if (output && !strcmp(output, "human")) { ++ output_format = OFORMAT_HUMAN; ++ } else if (output) { ++ error_report("--output must be used with human or json as argument."); ++ return 1; ++ } ++ ++ bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS, true, false); ++ if (!bs) { ++ return 1; ++ } ++ ++ if (output_format == OFORMAT_HUMAN) { ++ printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File"); ++ } ++ ++ length = bdrv_getlength(bs); ++ while (curr.start + curr.length < length) { ++ int64_t nsectors_left; ++ int64_t sector_num; ++ int n; ++ ++ sector_num = (curr.start + curr.length) >> BDRV_SECTOR_BITS; ++ ++ /* Probe up to 1 GiB at a time. */ ++ nsectors_left = DIV_ROUND_UP(length, BDRV_SECTOR_SIZE) - sector_num; ++ n = MIN(1 << (30 - BDRV_SECTOR_BITS), nsectors_left); ++ ret = get_block_status(bs, sector_num, n, &next); ++ ++ if (ret < 0) { ++ error_report("Could not read file metadata: %s", strerror(-ret)); ++ goto out; ++ } ++ ++ if (curr.length != 0 && curr.flags == next.flags && ++ curr.depth == next.depth && ++ ((curr.flags & BDRV_BLOCK_OFFSET_VALID) == 0 || ++ curr.offset + curr.length == next.offset)) { ++ curr.length += next.length; ++ continue; ++ } ++ ++ if (curr.length > 0) { ++ dump_map_entry(output_format, &curr, &next); ++ } ++ curr = next; ++ } ++ ++ dump_map_entry(output_format, &curr, NULL); ++ ++out: ++ bdrv_close(bs); ++ bdrv_delete(bs); ++ return ret < 0; ++} ++ + #define SNAPSHOT_LIST 1 + #define SNAPSHOT_CREATE 2 + #define SNAPSHOT_APPLY 3 +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-img-always-probe-the-input-image-for-allocated-.patch b/SOURCES/kvm-qemu-img-always-probe-the-input-image-for-allocated-.patch new file mode 100644 index 0000000..fda42c8 --- /dev/null +++ b/SOURCES/kvm-qemu-img-always-probe-the-input-image-for-allocated-.patch @@ -0,0 +1,94 @@ +From 76196ca1133605fa60365b6d00eff5b97fa758ea Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:35 +0200 +Subject: [PATCH 10/81] qemu-img: always probe the input image for allocated sectors + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-11-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54993 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 10/26] qemu-img: always probe the input image for allocated sectors +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +qemu-img convert can assume "that sectors which are unallocated in the +input image are present in both the output's and input's base images". + +However it is only doing this if the output image returns true for +bdrv_has_zero_init(). Testing bdrv_has_zero_init() does not make much +sense if the output image is copy-on-write, because a copy-on-write +image is never initialized to zero (it is initialized to the content +of the backing file). + +There is nothing here that makes has_zero_init images special. The +input and output must be equal for the operation to make sense, and +that's it. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit e4a86f88cc6b214c37b4abe9160e41f0338ce4cd) +--- + qemu-img.c | 40 +++++++++++++++++++--------------------- + 1 file changed, 19 insertions(+), 21 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-img.c | 40 +++++++++++++++++++--------------------- + 1 files changed, 19 insertions(+), 21 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 28efb4f..71cbc59 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1476,28 +1476,26 @@ static int img_convert(int argc, char **argv) + n = bs_offset + bs_sectors - sector_num; + } + +- if (has_zero_init) { +- /* If the output image is being created as a copy on write image, +- assume that sectors which are unallocated in the input image +- are present in both the output's and input's base images (no +- need to copy them). */ +- if (out_baseimg) { +- ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, +- n, &n1); +- if (ret < 0) { +- error_report("error while reading metadata for sector " +- "%" PRId64 ": %s", +- sector_num - bs_offset, strerror(-ret)); +- goto out; +- } +- if (!ret) { +- sector_num += n1; +- continue; +- } +- /* The next 'n1' sectors are allocated in the input image. Copy +- only those as they may be followed by unallocated sectors. */ +- n = n1; ++ /* If the output image is being created as a copy on write image, ++ assume that sectors which are unallocated in the input image ++ are present in both the output's and input's base images (no ++ need to copy them). */ ++ if (out_baseimg) { ++ ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, ++ n, &n1); ++ if (ret < 0) { ++ error_report("error while reading metadata for sector " ++ "%" PRId64 ": %s", ++ sector_num - bs_offset, strerror(-ret)); ++ goto out; ++ } ++ if (!ret) { ++ sector_num += n1; ++ continue; + } ++ /* The next 'n1' sectors are allocated in the input image. Copy ++ only those as they may be followed by unallocated sectors. */ ++ n = n1; + } else { + n1 = n; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-img-create-Emit-filename-on-error.patch b/SOURCES/kvm-qemu-img-create-Emit-filename-on-error.patch new file mode 100644 index 0000000..eeb343e --- /dev/null +++ b/SOURCES/kvm-qemu-img-create-Emit-filename-on-error.patch @@ -0,0 +1,50 @@ +From bb21b453413a2f98069fef482761982d1e90234a Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:13 +0100 +Subject: [PATCH 20/87] qemu-img create: Emit filename on error + +RH-Author: Max Reitz +Message-id: <1383604354-12743-23-git-send-email-mreitz@redhat.com> +Patchwork-id: 55322 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 22/43] qemu-img create: Emit filename on error +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +bdrv_img_create generally does not emit the target filename, although +this is pretty important information. Therefore, prepend its error +message with the output filename (if an error occurs). + +Signed-off-by: Max Reitz +(cherry picked from commit b70d8c237a0e5e829474c3a12c8783893c4e470e) + +Signed-off-by: Max Reitz +--- + qemu-img.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-img.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index 9fda8cf..0f869f3 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -409,7 +409,7 @@ static int img_create(int argc, char **argv) + bdrv_img_create(filename, fmt, base_filename, base_fmt, + options, img_size, BDRV_O_FLAGS, &local_err, quiet); + if (error_is_set(&local_err)) { +- error_report("%s", error_get_pretty(local_err)); ++ error_report("%s: %s", filename, error_get_pretty(local_err)); + error_free(local_err); + return 1; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-img-fix-invalid-JSON.patch b/SOURCES/kvm-qemu-img-fix-invalid-JSON.patch new file mode 100644 index 0000000..824caa8 --- /dev/null +++ b/SOURCES/kvm-qemu-img-fix-invalid-JSON.patch @@ -0,0 +1,45 @@ +From 7805c18f11162994f870271080ab0848759a6d07 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:48 +0200 +Subject: [PATCH 23/81] qemu-img: fix invalid JSON + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-24-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55006 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 23/26] qemu-img: fix invalid JSON +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Single quotes for JSON are a QMP-ism, use real JSON in +qemu-img output. + +Reported-by: Kevin Wolf +Signed-off-by: Paolo Bonzini +(cherry picked from commit c745bfb4300206280ce6156b4bafe765f610057c) +--- + qemu-img.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + qemu-img.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index e58c052..3a59bf0 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -1960,7 +1960,7 @@ static void dump_map_entry(OutputFormat output_format, MapEntry *e, + (e->flags & BDRV_BLOCK_ZERO) ? "true" : "false", + (e->flags & BDRV_BLOCK_DATA) ? "true" : "false"); + if (e->flags & BDRV_BLOCK_OFFSET_VALID) { +- printf(", 'offset': %"PRId64"", e->offset); ++ printf(", \"offset\": %"PRId64"", e->offset); + } + putchar('}'); + +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Add-basic-ability-to-use-binary-sample-.patch b/SOURCES/kvm-qemu-iotests-Add-basic-ability-to-use-binary-sample-.patch new file mode 100644 index 0000000..086565d --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Add-basic-ability-to-use-binary-sample-.patch @@ -0,0 +1,130 @@ +From 05d14f4ff759eed41146cc17688db92656388552 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:31 +0100 +Subject: [PATCH 74/87] qemu-iotests: Add basic ability to use binary sample images + +RH-Author: Max Reitz +Message-id: <1383756824-6921-9-git-send-email-mreitz@redhat.com> +Patchwork-id: 55563 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 08/21] qemu-iotests: Add basic ability to use binary sample images +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Jeff Cody + +BZ: 980771 + +For image formats that are not "QEMU native", but supported for +compatibility, it is useful to verify that an image created with +the 'gold standard' native tool can be read / written to successfully +by QEMU. + +In addition to testing non-native images, this could also be useful to +test against image files created by older versions of QEMU. + +This provides a directory to store small sample images, for use by +scripts in tests/qemu-iotests. + +Image files should be compressed with bzip2. + +To use a sample image from a bash script, the _use_sample_img function +will copy and decompress the image into $TEST_DIR, and set $TEST_IMG to +be the decompressed sample image copy. To cleanup, call +_cleanup_test_img as normal. + +Signed-off-by: Jeff Cody +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 85edbd375b9ab451c6769011cb6b3e0287dc71e4) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/common.config | 11 +++++++++++ + tests/qemu-iotests/common.rc | 16 ++++++++++++++++ + tests/qemu-iotests/sample_images/README | 8 ++++++++ + 3 files changed, 35 insertions(+) + create mode 100644 tests/qemu-iotests/sample_images/README + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/common.config | 11 +++++++++++ + tests/qemu-iotests/common.rc | 16 ++++++++++++++++ + tests/qemu-iotests/sample_images/README | 8 ++++++++ + 3 files changed, 35 insertions(+), 0 deletions(-) + create mode 100644 tests/qemu-iotests/sample_images/README + +diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config +index d794e62..d90a8bc 100644 +--- a/tests/qemu-iotests/common.config ++++ b/tests/qemu-iotests/common.config +@@ -125,6 +125,17 @@ fi + + export TEST_DIR + ++if [ -z "$SAMPLE_IMG_DIR" ]; then ++ SAMPLE_IMG_DIR=`pwd`/sample_images ++fi ++ ++if [ ! -d "$SAMPLE_IMG_DIR" ]; then ++ echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" ++ exit 1 ++fi ++ ++export SAMPLE_IMG_DIR ++ + _readlink() + { + if [ $# -ne 1 ]; then +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 28b39e4..6730955 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -91,6 +91,18 @@ _set_default_imgopts() + fi + } + ++_use_sample_img() ++{ ++ SAMPLE_IMG_FILE="${1%\.bz2}" ++ TEST_IMG="$TEST_DIR/$SAMPLE_IMG_FILE" ++ bzcat "$SAMPLE_IMG_DIR/$1" > "$TEST_IMG" ++ if [ $? -ne 0 ] ++ then ++ echo "_use_sample_img error, cannot extract '$SAMPLE_IMG_DIR/$1'" ++ exit 1 ++ fi ++} ++ + _make_test_img() + { + # extra qemu-img options can be added by tests +@@ -158,6 +170,10 @@ _cleanup_test_img() + rm -f $TEST_DIR/t.$IMGFMT + rm -f $TEST_DIR/t.$IMGFMT.orig + rm -f $TEST_DIR/t.$IMGFMT.base ++ if [ -n "$SAMPLE_IMG_FILE" ] ++ then ++ rm -f "$TEST_DIR/$SAMPLE_IMG_FILE" ++ fi + ;; + + rbd) +diff --git a/tests/qemu-iotests/sample_images/README b/tests/qemu-iotests/sample_images/README +new file mode 100644 +index 0000000..507af5f +--- /dev/null ++++ b/tests/qemu-iotests/sample_images/README +@@ -0,0 +1,8 @@ ++This is for small sample images to be used with qemu-iotests, intended for ++non-native formats that QEMU supports for compatibility. The idea is to use ++the native tool to create the sample image. ++ ++For instance, a VHDX image in this directory would be an image created not by ++QEMU itself, but rather created by Hyper-V. ++ ++Sample images added here must be compressed with bzip2. +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Additional-info-from-qemu-img-info.patch b/SOURCES/kvm-qemu-iotests-Additional-info-from-qemu-img-info.patch new file mode 100644 index 0000000..7c6648e --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Additional-info-from-qemu-img-info.patch @@ -0,0 +1,217 @@ +From 9769e7ac9ff2005316a655365c72c12a40579195 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:39 +0100 +Subject: [PATCH 82/87] qemu-iotests: Additional info from qemu-img info + +RH-Author: Max Reitz +Message-id: <1383756824-6921-17-git-send-email-mreitz@redhat.com> +Patchwork-id: 55571 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 16/21] qemu-iotests: Additional info from qemu-img info +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +Add a test for the additional information now provided by qemu-img info +when used on qcow2 images. It also tests the qemu QMP output from the +query-block command when running qemu with different runtime options +than specified in the image (ImageInfoSpecific should always refer to +the image). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 3677e6f6252542cbab85674d97d051d95e91693b) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/065 | 125 ++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/065.out | 5 ++ + tests/qemu-iotests/group | 1 + + tests/qemu-iotests/iotests.py | 4 ++ + 4 files changed, 135 insertions(+) + create mode 100755 tests/qemu-iotests/065 + create mode 100644 tests/qemu-iotests/065.out + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/065 | 125 +++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/065.out | 5 ++ + tests/qemu-iotests/group | 1 + + tests/qemu-iotests/iotests.py | 4 + + 4 files changed, 135 insertions(+), 0 deletions(-) + create mode 100755 tests/qemu-iotests/065 + create mode 100644 tests/qemu-iotests/065.out + +diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065 +new file mode 100755 +index 0000000..ab5445f +--- /dev/null ++++ b/tests/qemu-iotests/065 +@@ -0,0 +1,125 @@ ++#!/usr/bin/env python2 ++# ++# Test for additional information emitted by qemu-img info on qcow2 ++# images ++# ++# Copyright (C) 2013 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 . ++# ++ ++import os ++import re ++import json ++import iotests ++from iotests import qemu_img, qemu_img_pipe ++import unittest ++ ++test_img = os.path.join(iotests.test_dir, 'test.img') ++ ++class TestImageInfoSpecific(iotests.QMPTestCase): ++ '''Abstract base class for ImageInfoSpecific tests''' ++ ++ def setUp(self): ++ if self.img_options is None: ++ self.skipTest('Skipping abstract test class') ++ qemu_img('create', '-f', iotests.imgfmt, '-o', self.img_options, ++ test_img, '128K') ++ ++ def tearDown(self): ++ os.remove(test_img) ++ ++class TestQemuImgInfo(TestImageInfoSpecific): ++ '''Abstract base class for qemu-img info tests''' ++ ++ img_options = None ++ json_compare = None ++ human_compare = None ++ ++ def test_json(self): ++ data = json.loads(qemu_img_pipe('info', '--output=json', test_img)) ++ data = data['format-specific'] ++ self.assertEqual(data['type'], iotests.imgfmt) ++ self.assertEqual(data['data'], self.json_compare) ++ ++ def test_human(self): ++ data = qemu_img_pipe('info', '--output=human', test_img).split('\n') ++ data = data[(data.index('Format specific information:') + 1) ++ :data.index('')] ++ for field in data: ++ self.assertTrue(re.match('^ {4}[^ ]', field) is not None) ++ data = map(lambda line: line.strip(), data) ++ self.assertEqual(data, self.human_compare) ++ ++class TestQMP(TestImageInfoSpecific): ++ '''Abstract base class for qemu QMP tests''' ++ ++ img_options = None ++ qemu_options = '' ++ TestImageInfoSpecific = TestImageInfoSpecific ++ ++ def setUp(self): ++ self.TestImageInfoSpecific.setUp(self) ++ self.vm = iotests.VM().add_drive(test_img, self.qemu_options) ++ self.vm.launch() ++ ++ def tearDown(self): ++ self.vm.shutdown() ++ self.TestImageInfoSpecific.tearDown(self) ++ ++ def test_qmp(self): ++ result = self.vm.qmp('query-block')['return'] ++ drive = filter(lambda drive: drive['device'] == 'drive0', result)[0] ++ data = drive['inserted']['image']['format-specific'] ++ self.assertEqual(data['type'], iotests.imgfmt) ++ self.assertEqual(data['data'], self.compare) ++ ++class TestQCow2(TestQemuImgInfo): ++ '''Testing a qcow2 version 2 image''' ++ img_options = 'compat=0.10' ++ json_compare = { 'compat': '0.10' } ++ human_compare = [ 'compat: 0.10' ] ++ ++class TestQCow3NotLazy(TestQemuImgInfo): ++ '''Testing a qcow2 version 3 image with lazy refcounts disabled''' ++ img_options = 'compat=1.1,lazy_refcounts=off' ++ json_compare = { 'compat': '1.1', 'lazy-refcounts': False } ++ human_compare = [ 'compat: 1.1', 'lazy refcounts: false' ] ++ ++class TestQCow3Lazy(TestQemuImgInfo): ++ '''Testing a qcow2 version 3 image with lazy refcounts enabled''' ++ img_options = 'compat=1.1,lazy_refcounts=on' ++ json_compare = { 'compat': '1.1', 'lazy-refcounts': True } ++ human_compare = [ 'compat: 1.1', 'lazy refcounts: true' ] ++ ++class TestQCow3NotLazyQMP(TestQMP): ++ '''Testing a qcow2 version 3 image with lazy refcounts disabled, opening ++ with lazy refcounts enabled''' ++ img_options = 'compat=1.1,lazy_refcounts=off' ++ qemu_options = 'lazy-refcounts=on' ++ compare = { 'compat': '1.1', 'lazy-refcounts': False } ++ ++class TestQCow3LazyQMP(TestQMP): ++ '''Testing a qcow2 version 3 image with lazy refcounts enabled, opening ++ with lazy refcounts disabled''' ++ img_options = 'compat=1.1,lazy_refcounts=on' ++ qemu_options = 'lazy-refcounts=off' ++ compare = { 'compat': '1.1', 'lazy-refcounts': True } ++ ++TestImageInfoSpecific = None ++TestQemuImgInfo = None ++TestQMP = None ++ ++if __name__ == '__main__': ++ iotests.main(supported_fmts=['qcow2']) +diff --git a/tests/qemu-iotests/065.out b/tests/qemu-iotests/065.out +new file mode 100644 +index 0000000..594c16f +--- /dev/null ++++ b/tests/qemu-iotests/065.out +@@ -0,0 +1,5 @@ ++........ ++---------------------------------------------------------------------- ++Ran 8 tests ++ ++OK +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index d02ee96..68c056b 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -64,5 +64,6 @@ + 059 rw auto + 060 rw auto + 063 rw auto ++065 rw auto + 067 rw auto + 068 rw auto +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 569ca3d..5cbac82 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -46,6 +46,10 @@ def qemu_img_verbose(*args): + '''Run qemu-img without suppressing its output and return the exit code''' + return subprocess.call(qemu_img_args + list(args)) + ++def qemu_img_pipe(*args): ++ '''Run qemu-img and return its output''' ++ return subprocess.Popen(qemu_img_args + list(args), stdout=subprocess.PIPE).communicate()[0] ++ + def qemu_io(*args): + '''Run qemu-io and return the stdout data''' + args = qemu_io_args + list(args) +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Adjustments-due-to-error-propagation.patch b/SOURCES/kvm-qemu-iotests-Adjustments-due-to-error-propagation.patch new file mode 100644 index 0000000..b6fcd95 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Adjustments-due-to-error-propagation.patch @@ -0,0 +1,217 @@ +From aaf2d00ea8cd6479c5dd15773660e0699472af1c Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 12:37:40 +0100 +Subject: [PATCH 22/87] qemu-iotests: Adjustments due to error propagation + +RH-Author: Max Reitz +Message-id: <1383604354-12743-25-git-send-email-mreitz@redhat.com> +Patchwork-id: 55324 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 24/43] qemu-iotests: Adjustments due to error propagation +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1026524 + +When opening/creating images, propagating errors instead of immediately +emitting them on occurrence results in errors generally being printed on +a single line rather than being split up into multiple ones. This in +turn requires adjustments to some test results. + +Also, test 060 used a sed to filter out the test image directory and +format by removing everything from the affected line after a certain +keyword; this now also removes the error message itself, which can be +fixed by using _filter_testdir and _filter_imgfmt. + +Finally, _make_test_img in common.rc did not filter out the test image +directory etc. from stderr. This has been fixed through a redirection of +stderr to stdout (which is already done in _check_test_img and +_img_info). + +Signed-off-by: Max Reitz +(cherry picked from commit 2c78857bf6a9b5d06e17533b8f40fee14e087987) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/054.out + tests/qemu-iotests/060 + tests/qemu-iotests/060.out + +Conflicts because these tests do not exist downstream. +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/049.out | 18 +++++++----------- + tests/qemu-iotests/051.out | 35 ++++++++++++----------------------- + tests/qemu-iotests/common.rc | 2 +- + 3 files changed, 20 insertions(+), 35 deletions(-) + +diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out +index 72db13f..96e83a4 100644 +--- a/tests/qemu-iotests/049.out ++++ b/tests/qemu-iotests/049.out +@@ -96,7 +96,7 @@ qemu-img: Image size must be less than 8 EiB! + + qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2 + qemu-img: qcow2 doesn't support shrinking images yet +-qemu-img: Formatting or formatting option not supported for file format 'qcow2' ++qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k +@@ -104,7 +104,7 @@ qemu-img: Image size must be less than 8 EiB! + + qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2 + qemu-img: qcow2 doesn't support shrinking images yet +-qemu-img: Formatting or formatting option not supported for file format 'qcow2' ++qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte +@@ -120,7 +120,7 @@ qemu-img: kilobytes, megabytes, gigabytes and terabytes. + + qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2 + qemu-img: Parameter 'size' expects a size +-qemu-img: Invalid options for file format 'qcow2'. ++qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'. + + == Check correct interpretation of suffixes for cluster size == + +@@ -163,13 +163,11 @@ qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off + + qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M +-Invalid compatibility level: '0.42' +-qemu-img: TEST_DIR/t.qcow2: error while creating qcow2: Invalid argument ++qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42' + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off + + qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M +-Invalid compatibility level: 'foobar' +-qemu-img: TEST_DIR/t.qcow2: error while creating qcow2: Invalid argument ++qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar' + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off + + == Check preallocation option == +@@ -181,8 +179,7 @@ qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off + + qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M +-Invalid preallocation mode: '1234' +-qemu-img: TEST_DIR/t.qcow2: error while creating qcow2: Invalid argument ++qemu-img: TEST_DIR/t.qcow2: Invalid preallocation mode: '1234' + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off + + == Check encryption option == +@@ -205,8 +202,7 @@ qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off + + qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M +-Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) +-qemu-img: TEST_DIR/t.qcow2: error while creating qcow2: Invalid argument ++qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater) + Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on + + *** done +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index e3cf244..fe0b347 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -4,20 +4,16 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 + === Unknown option === + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt= +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234 +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not open disk image TEST_DIR/t.qcow2: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt' + + + === Enable and disable lazy refcounting on the command line, plus some invalid values === +@@ -31,24 +27,20 @@ QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts= +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: could not open disk image TEST_DIR/t.qcow2: Parameter 'lazy-refcounts' expects 'on' or 'off' + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42 +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: Parameter 'lazy-refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: could not open disk image TEST_DIR/t.qcow2: Parameter 'lazy-refcounts' expects 'on' or 'off' + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: Parameter 'lazy-refcounts' expects 'on' or 'off' +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Parameter 'lazy-refcounts' expects 'on' or 'off' + + + === With version 2 images enabling lazy refcounts must fail === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off + QEMU X.Y.Z monitor - type 'help' for more information +@@ -162,21 +154,18 @@ QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level +-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument ++QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Can't use 'qcow2' as a block driver for the protocol level + + + === Parsing protocol from file name === + + Testing: -hda foo:bar +-QEMU_PROG: -hda foo:bar: Unknown protocol +-QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory ++QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: Unknown protocol + + Testing: -drive file=foo:bar +-QEMU_PROG: -drive file=foo:bar: Unknown protocol +-QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory ++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: 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/common.rc b/tests/qemu-iotests/common.rc +index 1187b86..764a3eb 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -123,7 +123,7 @@ _make_test_img() + fi + + # XXX(hch): have global image options? +- $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size | \ ++ $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size 2>&1 | \ + sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Check-autodel-behaviour-for-device_del.patch b/SOURCES/kvm-qemu-iotests-Check-autodel-behaviour-for-device_del.patch new file mode 100644 index 0000000..56f3b04 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Check-autodel-behaviour-for-device_del.patch @@ -0,0 +1,292 @@ +From 489749c38620620dced8e638c7f8d724cbb81943 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Thu, 7 Nov 2013 12:49:49 +0100 +Subject: [PATCH 58/87] qemu-iotests: Check autodel behaviour for device_del + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-18-git-send-email-kwolf@redhat.com> +Patchwork-id: 55397 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 17/24] qemu-iotests: Check autodel behaviour for device_del +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +Block devices creates with -drive and drive_add should automatically +disappear if the guest device is unplugged. blockdev-add ones shouldn't. + +Signed-off-by: Kevin Wolf +Reviewed-by: Max Reitz +Reviewed-by: Eric Blake +(cherry picked from commit a9b43397a9782d028f45b63fb4affee164f85948) + +Conflicts: + tests/qemu-iotests/group + +Signed-off-by: Kevin Wolf +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/067 | 133 ++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/067.out | 80 +++++++++++++++++++++++ + tests/qemu-iotests/common.filter | 8 ++ + tests/qemu-iotests/group | 1 + + 4 files changed, 222 insertions(+), 0 deletions(-) + create mode 100644 tests/qemu-iotests/067 + create mode 100644 tests/qemu-iotests/067.out + +diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 +new file mode 100644 +index 0000000..79dc38b +--- /dev/null ++++ b/tests/qemu-iotests/067 +@@ -0,0 +1,133 @@ ++#!/bin/bash ++# ++# Test automatic deletion of BDSes created by -drive/drive_add ++# ++# Copyright (C) 2013 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! ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt qcow2 ++_supported_proto file ++_supported_os Linux ++ ++function do_run_qemu() ++{ ++ echo Testing: "$@" ++ $QEMU -nographic -qmp stdio -serial none "$@" ++ echo ++} ++ ++function run_qemu() ++{ ++ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp ++} ++ ++size=128M ++ ++_make_test_img $size ++ ++echo ++echo === -drive/-device and device_del === ++echo ++ ++run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0 < +Date: Wed, 6 Nov 2013 16:53:38 +0100 +Subject: [PATCH 81/87] qemu-iotests: Discard specific info in _img_info + +RH-Author: Max Reitz +Message-id: <1383756824-6921-16-git-send-email-mreitz@redhat.com> +Patchwork-id: 55570 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 15/21] qemu-iotests: Discard specific info in _img_info +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +BZ: 980771 + +In _img_info, filter out additional information specific to the image +format provided by qemu-img info, since tests designed for multiple +image formats would produce different outputs for every image format +otherwise. + +In a human-readable dump, that new information will always be last for +each "image information block" (multiple blocks are emitted when +inspecting the backing file chain). Every block is separated by an empty +line. Therefore, in this case, everything starting with the line "Format +specific information:" up to that empty line (or EOF, if it is the last +block) has to be stripped. + +The JSON dump will always emit pretty JSON data. Therefore, the opening +and closing braces of every object will be on lines which are indented +by exactly the same amount, and all lines in between will have more +indentation. Thus, in this case, everything starting with a line +matching the regular expression /^ *"format-specific": {/ until /^ *},?/ +has to be stripped, where the number of spaces at the beginning of the +respective lines is equal. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 4c2e946500c45685fdec61b3d929311dc26a2ad5) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/common.rc | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/common.rc | 20 +++++++++++++++++++- + 1 files changed, 19 insertions(+), 1 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 1b22db0..227c003 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -197,12 +197,30 @@ _check_test_img() + + _img_info() + { ++ discard=0 ++ regex_json_spec_start='^ *"format-specific": \{' + $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ + sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e "/^disk size:/ D" \ +- -e "/actual-size/ D" ++ -e "/actual-size/ D" | \ ++ while IFS='' read line; do ++ if [[ $line == "Format specific information:" ]]; then ++ discard=1 ++ elif [[ $line =~ $regex_json_spec_start ]]; then ++ discard=2 ++ regex_json_spec_end="^${line%%[^ ]*}\\},? *$" ++ fi ++ if [[ $discard == 0 ]]; then ++ echo "$line" ++ elif [[ $discard == 1 && ! $line ]]; then ++ echo ++ discard=0 ++ elif [[ $discard == 2 && $line =~ $regex_json_spec_end ]]; then ++ discard=0 ++ fi ++ done + } + + _get_pids_by_name() +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Fix-test-038.patch b/SOURCES/kvm-qemu-iotests-Fix-test-038.patch new file mode 100644 index 0000000..b877b11 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Fix-test-038.patch @@ -0,0 +1,89 @@ +From 8e9c1ae6f17f51f05a6e0cf5aacf8bbd7341eee4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 13 Sep 2013 10:37:12 +0200 +Subject: [PATCH 37/38] qemu-iotests: Fix test 038 + +Message-id: <1379499002-5231-6-git-send-email-mreitz@redhat.com> +Patchwork-id: 54436 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 5/6] qemu-iotests: Fix test 038 +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 + +Test 038 uses asynchronous I/O, resulting (potentially) in a different +output for every run (regarding the order of the I/O accesses). This can +be fixed by simply sorting the I/O access messages, since their order is +irrelevant anyway (for this asynchonous I/O). + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit c21bddf27fd8029890e9fc2ee314788919eababf) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/038 | 3 ++- + tests/qemu-iotests/038.out | 10 +++++----- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/tests/qemu-iotests/038 b/tests/qemu-iotests/038 +index 36125ea..90de1a7 100755 +--- a/tests/qemu-iotests/038 ++++ b/tests/qemu-iotests/038 +@@ -95,7 +95,8 @@ function overlay_io() + } + + overlay_io | $QEMU_IO $TEST_IMG | _filter_qemu_io |\ +- sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' ++ sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' \ ++ -e 's/qemu-io> //g' | paste - - | sort | tr '\t' '\n' + + echo + echo "== Verify image content ==" +diff --git a/tests/qemu-iotests/038.out b/tests/qemu-iotests/038.out +index 9cd0cd8..96c2f84 100644 +--- a/tests/qemu-iotests/038.out ++++ b/tests/qemu-iotests/038.out +@@ -517,7 +517,7 @@ qemu-io> wrote 65536/65536 bytes at offset 16711680 + qemu-io> Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base' + + == Some concurrent requests touching the same cluster == +-qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> qemu-io> wrote 65536/65536 bytes at offset XXX ++wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -577,8 +577,6 @@ wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-wrote 81920/81920 bytes at offset XXX +-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX +@@ -645,8 +643,6 @@ wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-wrote 81920/81920 bytes at offset XXX +-80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX +@@ -705,6 +701,10 @@ wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 65536/65536 bytes at offset XXX + 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 81920/81920 bytes at offset XXX ++80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++wrote 81920/81920 bytes at offset XXX ++80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + + == Verify image content == + qemu-io> read 4096/4096 bytes at offset 2064384 +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Fixed-test-case-026.patch b/SOURCES/kvm-qemu-iotests-Fixed-test-case-026.patch new file mode 100644 index 0000000..4b5246b --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Fixed-test-case-026.patch @@ -0,0 +1,828 @@ +From 9b1cfdf3f35a028aafffb01d667cdaf304e678c7 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 4 Sep 2013 13:16:05 +0200 +Subject: [PATCH 36/38] qemu-iotests: Fixed test case 026 + +Message-id: <1379499002-5231-5-git-send-email-mreitz@redhat.com> +Patchwork-id: 54435 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 4/6] qemu-iotests: Fixed test case 026 +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 + +The reference output for test case 026 hasn't been updated in a long +time and it's one of the "known failing" cases. This patch updates the +reference output so that unintentional changes can be reliably detected +again. + +The problem with this test case is that it produces different output +depending on whether -nocache is used or not. The solution of this patch +is to actually have two different reference outputs. If nnn.out.nocache +exists, it is used as the reference output for -nocache; otherwise, +nnn.out stays valid for both cases. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 8f94b077877151de93a63c73f796897309568ddb) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/026.out | 28 +- + tests/qemu-iotests/026.out.nocache | 626 ++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/check | 12 +- + 3 files changed, 649 insertions(+), 17 deletions(-) + create mode 100644 tests/qemu-iotests/026.out.nocache + +diff --git a/tests/qemu-iotests/026.out b/tests/qemu-iotests/026.out +index fb4f20e..0764389 100644 +--- a/tests/qemu-iotests/026.out ++++ b/tests/qemu-iotests/026.out +@@ -126,62 +126,64 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + Event: l2_update; errno: 5; imm: off; once: on; write + write failed: Input/output error + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 5; imm: off; once: on; write -b + write failed: Input/output error + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 5; imm: off; once: off; write + write failed: Input/output error + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 5; imm: off; once: off; write -b + write failed: Input/output error + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 28; imm: off; once: on; write + write failed: No space left on device + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 28; imm: off; once: on; write -b + write failed: No space left on device + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 28; imm: off; once: off; write + write failed: No space left on device + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_update; errno: 28; imm: off; once: off; write -b + write failed: No space left on device + +-128 leaked clusters were found on the image. ++127 leaked clusters were found on the image. + This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_alloc.write; errno: 5; imm: off; once: on; write + write failed: Input/output error +-No errors were found on the image. ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b +@@ -205,7 +207,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_alloc.write; errno: 28; imm: off; once: on; write + write failed: No space left on device +-No errors were found on the image. ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b +@@ -575,7 +579,6 @@ No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l1_grow.write_table; errno: 5; imm: off; once: off +-qcow2_free_clusters failed: Input/output error + write failed: Input/output error + No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +@@ -586,7 +589,6 @@ No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l1_grow.write_table; errno: 28; imm: off; once: off +-qcow2_free_clusters failed: No space left on device + write failed: No space left on device + No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 +@@ -597,7 +599,6 @@ No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l1_grow.activate_table; errno: 5; imm: off; once: off +-qcow2_free_clusters failed: Input/output error + write failed: Input/output error + + 96 leaked clusters were found on the image. +@@ -610,7 +611,6 @@ No errors were found on the image. + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 + + Event: l1_grow.activate_table; errno: 28; imm: off; once: off +-qcow2_free_clusters failed: No space left on device + write failed: No space left on device + + 96 leaked clusters were found on the image. +diff --git a/tests/qemu-iotests/026.out.nocache b/tests/qemu-iotests/026.out.nocache +new file mode 100644 +index 0000000..33bad0d +--- /dev/null ++++ b/tests/qemu-iotests/026.out.nocache +@@ -0,0 +1,626 @@ ++QA output created by 026 ++Errors while writing 128 kB ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_update; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 5; imm: off; once: on; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: Input/output error ++read failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 5; imm: off; once: on; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: Input/output error ++read failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 5; imm: off; once: off; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: Input/output error ++read failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 5; imm: off; once: off; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: Input/output error ++read failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 28; imm: off; once: on; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: No space left on device ++read failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 28; imm: off; once: on; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: No space left on device ++read failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 28; imm: off; once: off; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: No space left on device ++read failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_load; errno: 28; imm: off; once: off; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++write failed: No space left on device ++read failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 5; imm: off; once: on; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 5; imm: off; once: on; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 5; imm: off; once: off; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 5; imm: off; once: off; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 28; imm: off; once: on; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 28; imm: off; once: on; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 28; imm: off; once: off; write ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_update; errno: 28; imm: off; once: off; write -b ++wrote 131072/131072 bytes at offset 0 ++128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++127 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++1 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: write_aio; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_load; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_update_part; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 5; imm: off; once: on; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 5; imm: off; once: on; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 5; imm: off; once: off; write ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 5; imm: off; once: off; write -b ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: cluster_alloc; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++ ++=== Refcout table growth tests === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++ ++55 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++251 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++ ++10 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++23 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++ ++10 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++23 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write -b ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write ++write failed: No space left on device ++ ++10 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b ++write failed: No space left on device ++ ++23 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++ ++=== L1 growth tests === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.alloc_table; errno: 5; imm: off; once: on ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.alloc_table; errno: 5; imm: off; once: off ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.alloc_table; errno: 28; imm: off; once: on ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.alloc_table; errno: 28; imm: off; once: off ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.write_table; errno: 5; imm: off; once: on ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.write_table; errno: 5; imm: off; once: off ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.write_table; errno: 28; imm: off; once: on ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.write_table; errno: 28; imm: off; once: off ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.activate_table; errno: 5; imm: off; once: on ++write failed: Input/output error ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.activate_table; errno: 5; imm: off; once: off ++write failed: Input/output error ++ ++96 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.activate_table; errno: 28; imm: off; once: on ++write failed: No space left on device ++No errors were found on the image. ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 ++ ++Event: l1_grow.activate_table; errno: 28; imm: off; once: off ++write failed: No space left on device ++ ++96 leaked clusters were found on the image. ++This means waste of disk space, but no harm to data. ++*** done +diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check +index e51bae8..4ecf497 100755 +--- a/tests/qemu-iotests/check ++++ b/tests/qemu-iotests/check +@@ -239,12 +239,18 @@ do + echo -n " [failed, exit status $sts]" + err=true + fi +- if [ ! -f $seq.out ] ++ ++ reference=$seq.out ++ if (echo $QEMU_IO_OPTIONS | grep -s -- '--nocache' > /dev/null); then ++ [ -f $seq.out.nocache ] && reference=$seq.out.nocache ++ fi ++ ++ if [ ! -f $reference ] + then + echo " - no qualified output" + err=true + else +- if diff -w $seq.out $tmp.out >/dev/null 2>&1 ++ if diff -w $reference $tmp.out >/dev/null 2>&1 + then + echo "" + if $err +@@ -256,7 +262,7 @@ do + else + echo " - output mismatch (see $seq.out.bad)" + mv $tmp.out $seq.out.bad +- $diff -w $seq.out $seq.out.bad ++ $diff -w $reference $seq.out.bad + err=true + fi + fi +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Overlapping-cluster-allocations.patch b/SOURCES/kvm-qemu-iotests-Overlapping-cluster-allocations.patch new file mode 100644 index 0000000..f5ce436 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Overlapping-cluster-allocations.patch @@ -0,0 +1,218 @@ +From fdd55f6fb66d89ff7d241395419de8615e2063a4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 12:16:30 +0100 +Subject: [PATCH 13/87] qemu-iotests: Overlapping cluster allocations + +RH-Author: Max Reitz +Message-id: <1383604354-12743-16-git-send-email-mreitz@redhat.com> +Patchwork-id: 55315 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 15/43] qemu-iotests: Overlapping cluster allocations +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +A new test on corrupted images with overlapping cluster allocations. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit ca0eca91b65c34d6e5f5c77d5c18ed3de5b26139) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/group + +Conflicts because upstream contains more tests in the group file. +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/060 | 111 ++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/060.out | 44 +++++++++++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 156 insertions(+), 0 deletions(-) + create mode 100644 tests/qemu-iotests/060 + create mode 100644 tests/qemu-iotests/060.out + +diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060 +new file mode 100644 +index 0000000..65bb09f +--- /dev/null ++++ b/tests/qemu-iotests/060 +@@ -0,0 +1,111 @@ ++#!/bin/bash ++# ++# Test case for image corruption (overlapping data structures) in qcow2 ++# ++# Copyright (C) 2013 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 generic ++_supported_os Linux ++ ++rt_offset=65536 # 0x10000 (XXX: just an assumption) ++rb_offset=131072 # 0x20000 (XXX: just an assumption) ++l1_offset=196608 # 0x30000 (XXX: just an assumption) ++l2_offset=262144 # 0x40000 (XXX: just an assumption) ++ ++IMGOPTS="compat=1.1" ++ ++echo ++echo "=== Testing L2 reference into L1 ===" ++echo ++_make_test_img 64M ++# Link first L1 entry (first L2 table) onto itself ++# (Note the MSb in the L1 entry is set, ensuring the refcount is one - else any ++# later write will result in a COW operation, effectively ruining this attempt ++# on image corruption) ++poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x03\x00\x00" ++_check_test_img ++ ++# The corrupt bit should not be set anyway ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++# Try to write something, thereby forcing the corrupt bit to be set ++$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io ++ ++# The corrupt bit must now be set ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++# Try to open the image R/W (which should fail) ++$QEMU_IO -c "read 0 512" "$TEST_IMG" 2>&1 | _filter_qemu_io | sed -e "s/can't open device .*$/can't open device/" ++ ++# Try to open it RO (which should succeed) ++$QEMU_IO -c "read 0 512" -r "$TEST_IMG" | _filter_qemu_io ++ ++# We could now try to fix the image, but this would probably fail (how should an ++# L2 table linked onto the L1 table be fixed?) ++ ++echo ++echo "=== Testing cluster data reference into refcount block ===" ++echo ++_make_test_img 64M ++# Allocate L2 table ++truncate -s "$(($l2_offset+65536))" "$TEST_IMG" ++poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x00\x00" ++# Mark cluster as used ++poke_file "$TEST_IMG" "$(($rb_offset+8))" "\x00\x01" ++# Redirect new data cluster onto refcount block ++poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x02\x00\x00" ++_check_test_img ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++# Try to fix it ++_check_test_img -r all ++ ++# The corrupt bit should be cleared ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++# Look if it's really really fixed ++$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out +new file mode 100644 +index 0000000..ca4583a +--- /dev/null ++++ b/tests/qemu-iotests/060.out +@@ -0,0 +1,44 @@ ++QA output created by 060 ++ ++=== Testing L2 reference into L1 === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++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. ++write failed: Input/output error ++incompatible_features 0x2 ++qcow2: Image is corrupt; cannot be opened read/write. ++qemu-io: can't open device ++no file open, try 'help open' ++read 512/512 bytes at offset 0 ++512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++ ++=== Testing cluster data reference into refcount block === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++ERROR refcount block 0 refcount=2 ++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. ++write failed: Input/output error ++incompatible_features 0x2 ++Repairing refcount block 0 refcount=2 ++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. ++incompatible_features 0x0 ++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 ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 1017a19..9c8826d 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -61,4 +61,5 @@ + 052 rw auto backing + 053 rw auto + 059 rw auto ++060 rw auto + 068 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Quote-TEST_IMG-and-TEST_DIR-usage.patch b/SOURCES/kvm-qemu-iotests-Quote-TEST_IMG-and-TEST_DIR-usage.patch new file mode 100644 index 0000000..b62b740 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Quote-TEST_IMG-and-TEST_DIR-usage.patch @@ -0,0 +1,1971 @@ +From 75745b6eee8522c8b1eb05dc2be56f3245abae1b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:32 +0100 +Subject: [PATCH 75/87] qemu-iotests: Quote $TEST_IMG* and $TEST_DIR usage + +RH-Author: Max Reitz +Message-id: <1383756824-6921-10-git-send-email-mreitz@redhat.com> +Patchwork-id: 55564 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 09/21] qemu-iotests: Quote $TEST_IMG* and $TEST_DIR usage +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Jeff Cody + +BZ: 980771 + +A lot of image filename and paths are used unquoted. Quote these to +make sure that directories / filenames with spaces are not problematic. + +Signed-off-by: Jeff Cody +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit fef9c19139f4d69a080d99b8cbade163d0bbf0fc) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/051 + +Conflicts because of the downstream-only patch +9dcde11f25f85804f31d00fc45eed16595aebeec. +--- + tests/qemu-iotests/001 | 6 ++--- + tests/qemu-iotests/002 | 36 ++++++++++++------------- + tests/qemu-iotests/003 | 10 +++---- + tests/qemu-iotests/004 | 24 ++++++++--------- + tests/qemu-iotests/005 | 4 +-- + tests/qemu-iotests/007 | 2 +- + tests/qemu-iotests/008 | 6 ++--- + tests/qemu-iotests/009 | 2 +- + tests/qemu-iotests/010 | 2 +- + tests/qemu-iotests/011 | 2 +- + tests/qemu-iotests/012 | 4 +-- + tests/qemu-iotests/013 | 4 +-- + tests/qemu-iotests/014 | 2 +- + tests/qemu-iotests/015 | 16 +++++------ + tests/qemu-iotests/016 | 12 ++++----- + tests/qemu-iotests/018 | 6 ++--- + tests/qemu-iotests/019 | 12 ++++----- + tests/qemu-iotests/020 | 12 ++++----- + tests/qemu-iotests/021 | 2 +- + tests/qemu-iotests/023 | 4 +-- + tests/qemu-iotests/024 | 12 ++++----- + tests/qemu-iotests/025 | 4 +-- + tests/qemu-iotests/026 | 20 +++++++------- + tests/qemu-iotests/027 | 10 +++---- + tests/qemu-iotests/028 | 6 ++--- + tests/qemu-iotests/029 | 12 ++++----- + tests/qemu-iotests/031 | 12 ++++----- + tests/qemu-iotests/032 | 4 +-- + tests/qemu-iotests/033 | 18 ++++++------- + tests/qemu-iotests/034 | 64 ++++++++++++++++++++++---------------------- + tests/qemu-iotests/035 | 2 +- + tests/qemu-iotests/036 | 6 ++--- + tests/qemu-iotests/037 | 62 +++++++++++++++++++++--------------------- + tests/qemu-iotests/038 | 10 +++---- + tests/qemu-iotests/039 | 28 +++++++++---------- + tests/qemu-iotests/042 | 10 +++---- + tests/qemu-iotests/043 | 32 +++++++++++----------- + tests/qemu-iotests/046 | 10 +++---- + tests/qemu-iotests/047 | 2 +- + tests/qemu-iotests/048 | 8 +++--- + tests/qemu-iotests/049 | 36 ++++++++++++------------- + tests/qemu-iotests/050 | 20 +++++++------- + tests/qemu-iotests/051 | 50 +++++++++++++++++----------------- + tests/qemu-iotests/052 | 6 ++--- + tests/qemu-iotests/053 | 10 +++---- + tests/qemu-iotests/054 | 2 +- + tests/qemu-iotests/059 | 6 ++--- + tests/qemu-iotests/063 | 28 +++++++++---------- + tests/qemu-iotests/common.rc | 16 +++++------ + 49 files changed, 337 insertions(+), 337 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/001 | 6 ++-- + tests/qemu-iotests/002 | 36 ++++++++++++------------ + tests/qemu-iotests/003 | 10 +++--- + tests/qemu-iotests/004 | 24 ++++++++-------- + tests/qemu-iotests/005 | 4 +- + tests/qemu-iotests/007 | 2 +- + tests/qemu-iotests/008 | 6 ++-- + tests/qemu-iotests/009 | 2 +- + tests/qemu-iotests/010 | 2 +- + tests/qemu-iotests/011 | 2 +- + tests/qemu-iotests/012 | 4 +- + tests/qemu-iotests/013 | 4 +- + tests/qemu-iotests/014 | 2 +- + tests/qemu-iotests/015 | 16 +++++----- + tests/qemu-iotests/016 | 12 ++++---- + tests/qemu-iotests/018 | 6 ++-- + tests/qemu-iotests/019 | 12 ++++---- + tests/qemu-iotests/020 | 12 ++++---- + tests/qemu-iotests/021 | 2 +- + tests/qemu-iotests/023 | 4 +- + tests/qemu-iotests/024 | 12 ++++---- + tests/qemu-iotests/025 | 4 +- + tests/qemu-iotests/026 | 20 ++++++------ + tests/qemu-iotests/027 | 10 +++--- + tests/qemu-iotests/028 | 6 ++-- + tests/qemu-iotests/029 | 12 ++++---- + tests/qemu-iotests/031 | 12 ++++---- + tests/qemu-iotests/032 | 4 +- + tests/qemu-iotests/033 | 18 ++++++------ + tests/qemu-iotests/034 | 64 +++++++++++++++++++++--------------------- + tests/qemu-iotests/035 | 2 +- + tests/qemu-iotests/036 | 6 ++-- + tests/qemu-iotests/037 | 62 ++++++++++++++++++++-------------------- + tests/qemu-iotests/038 | 10 +++--- + tests/qemu-iotests/039 | 28 +++++++++--------- + tests/qemu-iotests/042 | 10 +++--- + tests/qemu-iotests/043 | 32 ++++++++++---------- + tests/qemu-iotests/046 | 10 +++--- + tests/qemu-iotests/047 | 2 +- + tests/qemu-iotests/048 | 8 ++-- + tests/qemu-iotests/049 | 36 ++++++++++++------------ + tests/qemu-iotests/050 | 20 ++++++------ + tests/qemu-iotests/051 | 50 ++++++++++++++++---------------- + tests/qemu-iotests/052 | 6 ++-- + tests/qemu-iotests/053 | 10 +++--- + tests/qemu-iotests/054 | 2 +- + tests/qemu-iotests/059 | 6 ++-- + tests/qemu-iotests/063 | 28 +++++++++--------- + tests/qemu-iotests/common.rc | 16 +++++----- + 49 files changed, 337 insertions(+), 337 deletions(-) + +diff --git a/tests/qemu-iotests/001 b/tests/qemu-iotests/001 +index bd88dde..4e16469 100755 +--- a/tests/qemu-iotests/001 ++++ b/tests/qemu-iotests/001 +@@ -48,15 +48,15 @@ _make_test_img $size + + echo + echo "== reading whole image ==" +-$QEMU_IO -c "read 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== rewriting whole image ==" +-$QEMU_IO -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify pattern ==" +-$QEMU_IO -c "read -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + + # success, all done +diff --git a/tests/qemu-iotests/002 b/tests/qemu-iotests/002 +index 51d0a8f..6a865aa 100755 +--- a/tests/qemu-iotests/002 ++++ b/tests/qemu-iotests/002 +@@ -48,36 +48,36 @@ _make_test_img $size + + echo + echo "== reading whole image ==" +-$QEMU_IO -c "read -p 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -p 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== rewriting whole image ==" +-$QEMU_IO -c "write -pP 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -pP 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify pattern ==" +-$QEMU_IO -c "read -pP 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -pP 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "unaligned pwrite" +-$QEMU_IO -c 'write -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'write -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'write -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'write -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'write -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c 'write -pP 0xab 66 42' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'write -pP 0xac 512 288' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'write -pP 0xad 800 224' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'write -pP 0xae 66000 128k' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'write -pP 0xaf 256k 42' "$TEST_IMG" | _filter_qemu_io + + echo + echo "verify pattern" +-$QEMU_IO -c 'read -pP 0xa 0 66' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xab 66 42' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xa 108 404' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xac 512 288' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xad 800 224' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xa 1k 64976' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xae 66000 128k' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xa 197072 65072' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xaf 256k 42' $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c 'read -pP 0xa 262186 470' $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xa 0 66' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xab 66 42' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xa 108 404' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xac 512 288' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xad 800 224' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xa 1k 64976' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xae 66000 128k' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xa 197072 65072' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xaf 256k 42' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c 'read -pP 0xa 262186 470' "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/003 b/tests/qemu-iotests/003 +index ee25fb8..98638d4 100755 +--- a/tests/qemu-iotests/003 ++++ b/tests/qemu-iotests/003 +@@ -50,27 +50,27 @@ _make_test_img $size + + echo + echo "== reading whole image ==" +-$QEMU_IO -c "readv 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "readv 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== rewriting whole image ==" +-$QEMU_IO -c "writev -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "writev -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify pattern ==" +-$QEMU_IO -c "readv -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "readv -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== vectored write ==" + $QEMU_IO -c "writev -P 0xb $offset $chunksize $chunksize \ + $chunksize $chunksize $chunksize $chunksize $chunksize" \ +- $TEST_IMG | _filter_qemu_io ++ "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify pattern ==" + $QEMU_IO -c "readv -P 0xb $offset $chunksize $chunksize \ + $chunksize $chunksize $chunksize $chunksize $chunksize" \ +- $TEST_IMG | _filter_qemu_io ++ "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/004 b/tests/qemu-iotests/004 +index c76451c..651072e 100755 +--- a/tests/qemu-iotests/004 ++++ b/tests/qemu-iotests/004 +@@ -51,51 +51,51 @@ _make_test_img $size + + echo + echo "write before image boundary" +-$QEMU_IO -c "write $pre_offset 1M" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write $pre_offset 1M" "$TEST_IMG" | _filter_qemu_io + + echo + echo "write into image boundary" +-$QEMU_IO -c "write $pre_offset 4M" $TEST_IMG ++$QEMU_IO -c "write $pre_offset 4M" "$TEST_IMG" + + echo + echo "write at image boundary" +-$QEMU_IO -c "write $size 4096" $TEST_IMG ++$QEMU_IO -c "write $size 4096" "$TEST_IMG" + + echo + echo "write past image boundary" +-$QEMU_IO -c "write $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "write $past_offset 4096" "$TEST_IMG" + + echo + echo "pwrite past image boundary" +-$QEMU_IO -c "write -p $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "write -p $past_offset 4096" "$TEST_IMG" + + echo + echo "writev past image boundary" +-$QEMU_IO -c "writev $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "writev $past_offset 4096" "$TEST_IMG" + + echo + echo "read before image boundary" +-$QEMU_IO -c "read $pre_offset 1M" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read $pre_offset 1M" "$TEST_IMG" | _filter_qemu_io + + echo + echo "read into image boundary" +-$QEMU_IO -c "read $pre_offset 4M" $TEST_IMG ++$QEMU_IO -c "read $pre_offset 4M" "$TEST_IMG" + + echo + echo "read at image boundary" +-$QEMU_IO -c "read $size 4096" $TEST_IMG ++$QEMU_IO -c "read $size 4096" "$TEST_IMG" + + echo + echo "read past image boundary" +-$QEMU_IO -c "read $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "read $past_offset 4096" "$TEST_IMG" + + echo + echo "pread past image boundary" +-$QEMU_IO -c "read -p $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "read -p $past_offset 4096" "$TEST_IMG" + + echo + echo "readv past image boundary" +-$QEMU_IO -c "readv $past_offset 4096" $TEST_IMG ++$QEMU_IO -c "readv $past_offset 4096" "$TEST_IMG" + + + # success, all done +diff --git a/tests/qemu-iotests/005 b/tests/qemu-iotests/005 +index b7970e3..9abcb84 100755 +--- a/tests/qemu-iotests/005 ++++ b/tests/qemu-iotests/005 +@@ -61,11 +61,11 @@ _make_test_img 5000G + + echo + echo "small read" +-$QEMU_IO -c "read 1024 4096" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read 1024 4096" "$TEST_IMG" | _filter_qemu_io + + echo + echo "small write" +-$QEMU_IO -c "write 8192 4096" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write 8192 4096" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/007 b/tests/qemu-iotests/007 +index c454f2c..fc84445 100755 +--- a/tests/qemu-iotests/007 ++++ b/tests/qemu-iotests/007 +@@ -50,7 +50,7 @@ _make_test_img 1M + + for i in `seq 1 10`; do + echo "savevm $i" +- $QEMU -nographic -hda $TEST_IMG -serial none -monitor stdio >/dev/null 2>&1 </dev/null 2>&1 < $TEST_DIR/blkdebug.conf < "$TEST_DIR/blkdebug.conf" < /dev/null 2>&1 ++ $QEMU_IO -c "write $vmstate 0 512" "$TEST_IMG" > /dev/null 2>&1 + fi + +-$QEMU_IO -c "write $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io + + # l2_load is not called on allocation, so issue a second write + # Reads are another path to trigger l2_load, so do a read, too + if [ "$event" == "l2_load" ]; then +- $QEMU_IO -c "write $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io +- $QEMU_IO -c "read $vmstate 0 128k " $BLKDBG_TEST_IMG | _filter_qemu_io ++ $QEMU_IO -c "write $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io ++ $QEMU_IO -c "read $vmstate 0 128k " "$BLKDBG_TEST_IMG" | _filter_qemu_io + fi + + _check_test_img 2>&1 | grep -v "refcount=1 reference=0" +@@ -133,7 +133,7 @@ for imm in off; do + for once in on off; do + for vmstate in "" "-b"; do + +-cat > $TEST_DIR/blkdebug.conf < "$TEST_DIR/blkdebug.conf" <&1 | grep -v "refcount=1 reference=0" + +@@ -172,7 +172,7 @@ for errno in 5 28; do + for imm in off; do + for once in on off; do + +-cat > $TEST_DIR/blkdebug.conf < "$TEST_DIR/blkdebug.conf" <&1 | grep -v "refcount=1 reference=0" + +diff --git a/tests/qemu-iotests/027 b/tests/qemu-iotests/027 +index 7d90481..3fa81b8 100755 +--- a/tests/qemu-iotests/027 ++++ b/tests/qemu-iotests/027 +@@ -54,23 +54,23 @@ _make_test_img $size + # Otherwise an L2 table could get in the way after the data cluster. + echo + echo "== writing first cluster to populate metadata ==" +-$QEMU_IO -c "write -pP 0xde $cluster_size $cluster_size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -pP 0xde $cluster_size $cluster_size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== writing at sub-cluster granularity ==" +-$QEMU_IO -c "write -pP 0xa $subcluster_offset $subcluster_size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -pP 0xa $subcluster_offset $subcluster_size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify pattern ==" +-$QEMU_IO -c "read -pP 0xa $subcluster_offset $subcluster_size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -pP 0xa $subcluster_offset $subcluster_size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify zeroes before sub-cluster pattern ==" +-$QEMU_IO -c "read -pP 0 -l $subcluster_offset 0 $subcluster_size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -pP 0 -l $subcluster_offset 0 $subcluster_size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== verify zeroes after sub-cluster pattern ==" +-$QEMU_IO -c "read -pP 0 -l 512 -s $subcluster_size $subcluster_offset $(( subcluster_size + 512 ))" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -pP 0 -l 512 -s $subcluster_size $subcluster_offset $(( subcluster_size + 512 ))" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028 +index b091ba9..93a9fa6 100755 +--- a/tests/qemu-iotests/028 ++++ b/tests/qemu-iotests/028 +@@ -71,8 +71,8 @@ _check_test_img + echo "Creating test image with backing file" + echo + +-mv $TEST_IMG $TEST_IMG.base +-_make_test_img -b $TEST_IMG.base $image_size ++mv "$TEST_IMG" "$TEST_IMG.base" ++_make_test_img -b "$TEST_IMG.base" $image_size + + echo "Filling test image" + echo +@@ -97,7 +97,7 @@ io_zero readv $(( offset + 32 * 1024 )) 512 1024 32 + _check_test_img + + # Rebase it on top of its base image +-$QEMU_IMG rebase -b $TEST_IMG.base $TEST_IMG ++$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG" + + _check_test_img + +diff --git a/tests/qemu-iotests/029 b/tests/qemu-iotests/029 +index 0ad5e45..b424726 100755 +--- a/tests/qemu-iotests/029 ++++ b/tests/qemu-iotests/029 +@@ -47,16 +47,16 @@ _supported_os Linux + + CLUSTER_SIZE=65536 + _make_test_img 64M +-$QEMU_IMG snapshot -c foo $TEST_IMG +-$QEMU_IO -c 'write -b 0 4k' $TEST_IMG | _filter_qemu_io +-$QEMU_IMG snapshot -a foo $TEST_IMG ++$QEMU_IMG snapshot -c foo "$TEST_IMG" ++$QEMU_IO -c 'write -b 0 4k' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG snapshot -a foo "$TEST_IMG" + _check_test_img + + CLUSTER_SIZE=1024 + _make_test_img 16M +-$QEMU_IMG snapshot -c foo $TEST_IMG +-$QEMU_IO -c 'write -b 0 4M' $TEST_IMG | _filter_qemu_io +-$QEMU_IMG snapshot -a foo $TEST_IMG ++$QEMU_IMG snapshot -c foo "$TEST_IMG" ++$QEMU_IO -c 'write -b 0 4M' "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG snapshot -a foo "$TEST_IMG" + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031 +index 2d5e3b1..c9070b0 100755 +--- a/tests/qemu-iotests/031 ++++ b/tests/qemu-iotests/031 +@@ -56,22 +56,22 @@ for IMGOPTS in "compat=0.10" "compat=1.1"; do + echo === Create image with unknown header extension === + echo + _make_test_img 64M +- ./qcow2.py $TEST_IMG add-header-ext 0x12345678 "This is a test header extension" +- ./qcow2.py $TEST_IMG dump-header ++ ./qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension" ++ ./qcow2.py "$TEST_IMG" dump-header + _check_test_img + + echo + echo === Rewrite header with no backing file === + echo +- $QEMU_IMG rebase -u -b "" $TEST_IMG +- ./qcow2.py $TEST_IMG dump-header ++ $QEMU_IMG rebase -u -b "" "$TEST_IMG" ++ ./qcow2.py "$TEST_IMG" dump-header + _check_test_img + + echo + echo === Add a backing file and format === + echo +- $QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device $TEST_IMG +- ./qcow2.py $TEST_IMG dump-header ++ $QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device "$TEST_IMG" ++ ./qcow2.py "$TEST_IMG" dump-header + done + + # success, all done +diff --git a/tests/qemu-iotests/032 b/tests/qemu-iotests/032 +index 7155568..b1ba5c3 100755 +--- a/tests/qemu-iotests/032 ++++ b/tests/qemu-iotests/032 +@@ -55,12 +55,12 @@ _make_test_img 64M + + # Allocate every other cluster so that afterwards a big write request will + # actually loop a while and issue many I/O requests for the lower layer +-for i in $(seq 0 128 4096); do echo "write ${i}k 64k"; done | $QEMU_IO $TEST_IMG | _filter_qemu_io ++for i in $(seq 0 128 4096); do echo "write ${i}k 64k"; done | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + echo + echo === AIO request during close === + echo +-$QEMU_IO -c "aio_write 0 4M" -c "close" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "aio_write 0 4M" -c "close" "$TEST_IMG" | _filter_qemu_io + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/033 b/tests/qemu-iotests/033 +index 9aee078..ea3351c 100755 +--- a/tests/qemu-iotests/033 ++++ b/tests/qemu-iotests/033 +@@ -48,24 +48,24 @@ _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 ++$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 + + 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 ++$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 "== 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 ++$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 "== verifying patterns (2) ==" +-$QEMU_IO -c "read -P 0x0 0x400 0x20000" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/034 b/tests/qemu-iotests/034 +index 8254df8..67f1959 100755 +--- a/tests/qemu-iotests/034 ++++ b/tests/qemu-iotests/034 +@@ -49,63 +49,63 @@ echo + echo "== creating backing file for COW tests ==" + + _make_test_img $size +-$QEMU_IO -c "write -P 0x55 0 1M" $TEST_IMG | _filter_qemu_io +-mv $TEST_IMG $TEST_IMG.base ++$QEMU_IO -c "write -P 0x55 0 1M" "$TEST_IMG" | _filter_qemu_io ++mv "$TEST_IMG" "$TEST_IMG.base" + +-_make_test_img -b $TEST_IMG.base 6G ++_make_test_img -b "$TEST_IMG.base" 6G + + echo + echo "== zero write with backing file ==" +-$QEMU_IO -c "write -z 64k 192k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -z 513k 13k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -z 64k 192k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -z 513k 13k" "$TEST_IMG" | _filter_qemu_io + + _check_test_img + + echo + echo "== verifying patterns (3) ==" +-$QEMU_IO -c "read -P 0x55 0 64k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 64k 192k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x55 256k 257k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 513k 13k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x55 526k 498k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 0 64k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 64k 192k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 256k 257k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 513k 13k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 526k 498k" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== overwriting zero cluster ==" +-$QEMU_IO -c "write -P 0xa 60k 8k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0xb 64k 8k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0xc 76k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0xd 252k 8k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0xe 248k 8k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0xa 60k 8k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0xb 64k 8k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0xc 76k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0xd 252k 8k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0xe 248k 8k" "$TEST_IMG" | _filter_qemu_io + + _check_test_img + + echo + echo "== verifying patterns (4) ==" +-$QEMU_IO -c "read -P 0x55 0 60k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xa 60k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xb 64k 8k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 72k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xc 76k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 80k 168k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xe 248k 8k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xd 256k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x55 260k 64k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 0 60k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xa 60k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xb 64k 8k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 72k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xc 76k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 80k 168k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xe 248k 8k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xd 256k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 260k 64k" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== re-zeroing overwritten area ==" +-$QEMU_IO -c "write -z 64k 192k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -z 64k 192k" "$TEST_IMG" | _filter_qemu_io + + _check_test_img + + echo + echo "== verifying patterns (5) ==" +-$QEMU_IO -c "read -P 0x55 0 60k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xa 60k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 64k 192k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0xd 256k 4k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x55 260k 253k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x0 513k 13k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x55 526k 498k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 0 60k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xa 60k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 64k 192k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0xd 256k 4k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 260k 253k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x0 513k 13k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x55 526k 498k" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/035 b/tests/qemu-iotests/035 +index 9d2d347..ebe9b8c 100755 +--- a/tests/qemu-iotests/035 ++++ b/tests/qemu-iotests/035 +@@ -59,7 +59,7 @@ function generate_requests() { + done + } + +-generate_requests | $QEMU_IO $TEST_IMG | _filter_qemu_io |\ ++generate_requests | $QEMU_IO "$TEST_IMG" | _filter_qemu_io |\ + sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' + + echo +diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036 +index 4dbfc57..e049a64 100755 +--- a/tests/qemu-iotests/036 ++++ b/tests/qemu-iotests/036 +@@ -53,15 +53,15 @@ IMGOPTS="compat=1.1" + echo === Create image with unknown autoclear feature bit === + echo + _make_test_img 64M +-./qcow2.py $TEST_IMG set-feature-bit autoclear 63 +-./qcow2.py $TEST_IMG dump-header ++./qcow2.py "$TEST_IMG" set-feature-bit autoclear 63 ++./qcow2.py "$TEST_IMG" dump-header + + echo + echo === Repair image === + echo + _check_test_img -r all + +-./qcow2.py $TEST_IMG dump-header ++./qcow2.py "$TEST_IMG" dump-header + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/037 b/tests/qemu-iotests/037 +index c11460b..743bae3 100755 +--- a/tests/qemu-iotests/037 ++++ b/tests/qemu-iotests/037 +@@ -66,50 +66,50 @@ function backing_io() + done + } + +-backing_io 0 256 write | $QEMU_IO $TEST_IMG | _filter_qemu_io ++backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + +-mv $TEST_IMG $TEST_IMG.base ++mv "$TEST_IMG" "$TEST_IMG.base" + +-_make_test_img -b $TEST_IMG.base 6G ++_make_test_img -b "$TEST_IMG.base" 6G + + echo + echo "== COW in a single cluster ==" +-$QEMU_IO -c "write -P 0x77 0 2k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x88 6k 2k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x99 9k 2k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x77 0 2k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x88 6k 2k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x99 9k 2k" "$TEST_IMG" | _filter_qemu_io + +-$QEMU_IO -c "read -P 0x77 0 2k" $TEST_IMG | _filter_qemu_io +-backing_io $((2 * 1024)) 8 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x88 6k 2k" $TEST_IMG | _filter_qemu_io +-backing_io $((8 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x99 9k 2k" $TEST_IMG | _filter_qemu_io +-backing_io $((11 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x77 0 2k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((2 * 1024)) 8 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x88 6k 2k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((8 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x99 9k 2k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((11 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + echo + echo "== COW in two-cluster allocations ==" +-$QEMU_IO -c "write -P 0x77 16k 6k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x88 26k 6k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x99 33k 5k" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x77 16k 6k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x88 26k 6k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x99 33k 5k" "$TEST_IMG" | _filter_qemu_io + +-$QEMU_IO -c "read -P 0x77 16k 6k" $TEST_IMG | _filter_qemu_io +-backing_io $((22 * 1024)) 8 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x88 26k 6k" $TEST_IMG | _filter_qemu_io +-backing_io $((32 * 1024)) 2 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x99 33k 5k" $TEST_IMG | _filter_qemu_io +-backing_io $((38 * 1024)) 4 read | $QEMU_IO $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x77 16k 6k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((22 * 1024)) 8 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x88 26k 6k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((32 * 1024)) 2 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x99 33k 5k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((38 * 1024)) 4 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + echo + echo "== COW in multi-cluster allocations ==" +-$QEMU_IO -c "write -P 0x77 48k 15k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x88 66k 14k" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "write -P 0x99 83k 15k" $TEST_IMG | _filter_qemu_io +- +-$QEMU_IO -c "read -P 0x77 48k 15k" $TEST_IMG | _filter_qemu_io +-backing_io $((63 * 1024)) 6 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x88 66k 14k" $TEST_IMG | _filter_qemu_io +-backing_io $((80 * 1024)) 6 read | $QEMU_IO $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0x99 83k 15k" $TEST_IMG | _filter_qemu_io +-backing_io $((98 * 1024)) 4 read | $QEMU_IO $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x77 48k 15k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x88 66k 14k" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "write -P 0x99 83k 15k" "$TEST_IMG" | _filter_qemu_io ++ ++$QEMU_IO -c "read -P 0x77 48k 15k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((63 * 1024)) 6 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x88 66k 14k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((80 * 1024)) 6 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0x99 83k 15k" "$TEST_IMG" | _filter_qemu_io ++backing_io $((98 * 1024)) 4 read | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + _check_test_img + +diff --git a/tests/qemu-iotests/038 b/tests/qemu-iotests/038 +index 90de1a7..7bb7906 100755 +--- a/tests/qemu-iotests/038 ++++ b/tests/qemu-iotests/038 +@@ -66,11 +66,11 @@ function backing_io() + done + } + +-backing_io 0 256 write | $QEMU_IO $TEST_IMG | _filter_qemu_io ++backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + +-mv $TEST_IMG $TEST_IMG.base ++mv "$TEST_IMG" "$TEST_IMG.base" + +-_make_test_img -b $TEST_IMG.base 6G ++_make_test_img -b "$TEST_IMG.base" 6G + + echo + echo "== Some concurrent requests touching the same cluster ==" +@@ -94,7 +94,7 @@ function overlay_io() + echo aio_write -P 0x90 4080k 80k + } + +-overlay_io | $QEMU_IO $TEST_IMG | _filter_qemu_io |\ ++overlay_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io |\ + sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' \ + -e 's/qemu-io> //g' | paste - - | sort | tr '\t' '\n' + +@@ -124,7 +124,7 @@ function verify_io() + done + } + +-verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io ++verify_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + _check_test_img + +diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 +index ae35175..f85b4ce 100755 +--- a/tests/qemu-iotests/039 ++++ b/tests/qemu-iotests/039 +@@ -54,10 +54,10 @@ echo "== Checking that image is clean on shutdown ==" + IMGOPTS="compat=1.1,lazy_refcounts=on" + _make_test_img $size + +-$QEMU_IO -c "write -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x5a 0 512" ""$TEST_IMG"" | _filter_qemu_io + + # The dirty bit must not be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + _check_test_img + + echo +@@ -68,20 +68,20 @@ _make_test_img $size + + old_ulimit=$(ulimit -c) + ulimit -c 0 # do not produce a core dump on abort(3) +-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io + ulimit -c "$old_ulimit" + + # The dirty bit must be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + _check_test_img + + echo + echo "== Read-only access must still work ==" + +-$QEMU_IO -r -c "read -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -r -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io + + # The dirty bit must be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + + echo + echo "== Repairing the image file must succeed ==" +@@ -89,12 +89,12 @@ echo "== Repairing the image file must succeed ==" + _check_test_img -r all + + # The dirty bit must not be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + + echo + echo "== Data should still be accessible after repair ==" + +-$QEMU_IO -c "read -P 0x5a 0 512" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== Opening a dirty image read/write should repair it ==" +@@ -104,16 +104,16 @@ _make_test_img $size + + old_ulimit=$(ulimit -c) + ulimit -c 0 # do not produce a core dump on abort(3) +-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io + ulimit -c "$old_ulimit" + + # The dirty bit must be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + +-$QEMU_IO -c "write 0 512" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io + + # The dirty bit must not be set +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + + echo + echo "== Creating an image file with lazy_refcounts=off ==" +@@ -123,11 +123,11 @@ _make_test_img $size + + old_ulimit=$(ulimit -c) + ulimit -c 0 # do not produce a core dump on abort(3) +-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io + ulimit -c "$old_ulimit" + + # The dirty bit must not be set since lazy_refcounts=off +-./qcow2.py $TEST_IMG dump-header | grep incompatible_features ++./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/042 b/tests/qemu-iotests/042 +index 16b2fdb..94ce3a9 100755 +--- a/tests/qemu-iotests/042 ++++ b/tests/qemu-iotests/042 +@@ -48,27 +48,27 @@ echo "== Creating zero size image ==" + _make_test_img 0 + _check_test_img + +-mv $TEST_IMG $TEST_IMG.orig ++mv "$TEST_IMG" "$TEST_IMG.orig" + + echo + echo "== Converting the image ==" + +-$QEMU_IMG convert -O $IMGFMT $TEST_IMG.orig $TEST_IMG ++$QEMU_IMG convert -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG" + _check_test_img + + echo + echo "== Converting the image, compressed ==" + + if [ "$IMGFMT" == "qcow2" ]; then +- $QEMU_IMG convert -c -O $IMGFMT $TEST_IMG.orig $TEST_IMG ++ $QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG" + fi + _check_test_img + + echo + echo "== Rebasing the image ==" + +-$QEMU_IMG rebase -u -b $TEST_IMG.orig $TEST_IMG +-$QEMU_IMG rebase -b $TEST_IMG.orig $TEST_IMG ++$QEMU_IMG rebase -u -b "$TEST_IMG.orig" "$TEST_IMG" ++$QEMU_IMG rebase -b "$TEST_IMG.orig" "$TEST_IMG" + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/043 b/tests/qemu-iotests/043 +index 478773d..d7f1231 100755 +--- a/tests/qemu-iotests/043 ++++ b/tests/qemu-iotests/043 +@@ -31,7 +31,7 @@ status=1 # failure is the default! + _cleanup() + { + _cleanup_test_img +- rm -f $TEST_IMG.[123].base ++ rm -f "$TEST_IMG".[123].base + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -47,39 +47,39 @@ _supported_os Linux + + size=128M + _make_test_img $size +-$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG ++$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG" + + echo + echo "== backing file references self ==" + _img_info --backing-chain + + _make_test_img $size +-mv $TEST_IMG $TEST_IMG.base +-_make_test_img -b $TEST_IMG.base $size +-$QEMU_IMG rebase -u -b $TEST_IMG $TEST_IMG.base ++mv "$TEST_IMG" "$TEST_IMG.base" ++_make_test_img -b "$TEST_IMG.base" $size ++$QEMU_IMG rebase -u -b "$TEST_IMG" "$TEST_IMG.base" + + echo + echo "== parent references self ==" + _img_info --backing-chain + + _make_test_img $size +-mv $TEST_IMG $TEST_IMG.1.base +-_make_test_img -b $TEST_IMG.1.base $size +-mv $TEST_IMG $TEST_IMG.2.base +-_make_test_img -b $TEST_IMG.2.base $size +-mv $TEST_IMG $TEST_IMG.3.base +-_make_test_img -b $TEST_IMG.3.base $size +-$QEMU_IMG rebase -u -b $TEST_IMG.2.base $TEST_IMG.1.base ++mv "$TEST_IMG" "$TEST_IMG.1.base" ++_make_test_img -b "$TEST_IMG.1.base" $size ++mv "$TEST_IMG" "$TEST_IMG.2.base" ++_make_test_img -b "$TEST_IMG.2.base" $size ++mv "$TEST_IMG" "$TEST_IMG.3.base" ++_make_test_img -b "$TEST_IMG.3.base" $size ++$QEMU_IMG rebase -u -b "$TEST_IMG.2.base" "$TEST_IMG.1.base" + + echo + echo "== ancestor references another ancestor ==" + _img_info --backing-chain + + _make_test_img $size +-mv $TEST_IMG $TEST_IMG.1.base +-_make_test_img -b $TEST_IMG.1.base $size +-mv $TEST_IMG $TEST_IMG.2.base +-_make_test_img -b $TEST_IMG.2.base $size ++mv "$TEST_IMG" "$TEST_IMG.1.base" ++_make_test_img -b "$TEST_IMG.1.base" $size ++mv "$TEST_IMG" "$TEST_IMG.2.base" ++_make_test_img -b "$TEST_IMG.2.base" $size + + echo + echo "== finite chain of length 3 (human) ==" +diff --git a/tests/qemu-iotests/046 b/tests/qemu-iotests/046 +index 987bfff..3f17ceb 100755 +--- a/tests/qemu-iotests/046 ++++ b/tests/qemu-iotests/046 +@@ -66,11 +66,11 @@ function backing_io() + done + } + +-backing_io 0 32 write | $QEMU_IO $TEST_IMG | _filter_qemu_io ++backing_io 0 32 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + +-mv $TEST_IMG $TEST_IMG.base ++mv "$TEST_IMG" "$TEST_IMG.base" + +-_make_test_img -b $TEST_IMG.base 6G ++_make_test_img -b "$TEST_IMG.base" 6G + + echo + echo "== Some concurrent requests touching the same cluster ==" +@@ -185,7 +185,7 @@ aio_flush + EOF + } + +-overlay_io | $QEMU_IO blkdebug::$TEST_IMG | _filter_qemu_io |\ ++overlay_io | $QEMU_IO blkdebug::"$TEST_IMG" | _filter_qemu_io |\ + sed -e 's/bytes at offset [0-9]*/bytes at offset XXX/g' + + echo +@@ -252,7 +252,7 @@ function verify_io() + echo read -P 17 0x11c000 0x4000 + } + +-verify_io | $QEMU_IO $TEST_IMG | _filter_qemu_io ++verify_io | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + + _check_test_img + +diff --git a/tests/qemu-iotests/047 b/tests/qemu-iotests/047 +index 0cf36b4..c35cd09 100755 +--- a/tests/qemu-iotests/047 ++++ b/tests/qemu-iotests/047 +@@ -66,7 +66,7 @@ read -P 0x55 1M 128k + EOF + } + +-qemu_io_cmds | $QEMU_IO $TEST_IMG | _filter_qemu_io ++qemu_io_cmds | $QEMU_IO "$TEST_IMG" | _filter_qemu_io + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/048 b/tests/qemu-iotests/048 +index 7cce049..9b9d118 100755 +--- a/tests/qemu-iotests/048 ++++ b/tests/qemu-iotests/048 +@@ -31,13 +31,13 @@ _cleanup() + { + echo "Cleanup" + _cleanup_test_img +- rm ${TEST_IMG2} ++ rm "${TEST_IMG2}" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + + _compare() + { +- $QEMU_IMG compare "$@" $TEST_IMG ${TEST_IMG2} ++ $QEMU_IMG compare "$@" "$TEST_IMG" "${TEST_IMG2}" + echo $? + } + +@@ -59,12 +59,12 @@ _make_test_img $size + io_pattern write 524288 $CLUSTER_SIZE $CLUSTER_SIZE 4 45 + + # Compare identical images +-cp $TEST_IMG ${TEST_IMG2} ++cp "$TEST_IMG" "${TEST_IMG2}" + _compare + _compare -q + + # Compare images with different size +-$QEMU_IMG resize $TEST_IMG +512M ++$QEMU_IMG resize "$TEST_IMG" +512M + _compare + _compare -s + +diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049 +index 6c6017e..93aa0ea 100755 +--- a/tests/qemu-iotests/049 ++++ b/tests/qemu-iotests/049 +@@ -63,13 +63,13 @@ sizes+="1024.0 1024.0b 1.5k 1.5K 1.5M 1.5G 1.5T" + echo "== 1. Traditional size parameter ==" + echo + for s in $sizes; do +- test_qemu_img create -f $IMGFMT $TEST_IMG $s ++ test_qemu_img create -f $IMGFMT "$TEST_IMG" $s + done + + echo "== 2. Specifying size via -o ==" + echo + for s in $sizes; do +- test_qemu_img create -f $IMGFMT -o size=$s $TEST_IMG ++ test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG" + done + + echo "== 3. Invalid sizes ==" +@@ -77,8 +77,8 @@ echo + sizes="-1024 -1k 1kilobyte foobar" + + for s in $sizes; do +- test_qemu_img create -f $IMGFMT $TEST_IMG -- $s +- test_qemu_img create -f $IMGFMT -o size=$s $TEST_IMG ++ test_qemu_img create -f $IMGFMT "$TEST_IMG" -- $s ++ test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG" + done + + echo "== Check correct interpretation of suffixes for cluster size ==" +@@ -87,35 +87,35 @@ sizes="1024 1024b 1k 1K 1M " + sizes+="1024.0 1024.0b 0.5k 0.5K 0.5M" + + for s in $sizes; do +- test_qemu_img create -f $IMGFMT -o cluster_size=$s $TEST_IMG 64M ++ test_qemu_img create -f $IMGFMT -o cluster_size=$s "$TEST_IMG" 64M + done + + echo "== Check compat level option ==" + echo +-test_qemu_img create -f $IMGFMT -o compat=0.10 $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o compat=1.1 $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o compat=0.10 "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o compat=1.1 "$TEST_IMG" 64M + +-test_qemu_img create -f $IMGFMT -o compat=0.42 $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o compat=foobar $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o compat=0.42 "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o compat=foobar "$TEST_IMG" 64M + + echo "== Check preallocation option ==" + echo +-test_qemu_img create -f $IMGFMT -o preallocation=off $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o preallocation=metadata $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o preallocation=1234 $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o preallocation=off "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o preallocation=metadata "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o preallocation=1234 "$TEST_IMG" 64M + + echo "== Check encryption option ==" + echo +-test_qemu_img create -f $IMGFMT -o encryption=off $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o encryption=on $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o encryption=off "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o encryption=on "$TEST_IMG" 64M + + echo "== Check lazy_refcounts option (only with v3) ==" + echo +-test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=off $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=off "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o compat=1.1,lazy_refcounts=on "$TEST_IMG" 64M + +-test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off $TEST_IMG 64M +-test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on $TEST_IMG 64M ++test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=off "$TEST_IMG" 64M ++test_qemu_img create -f $IMGFMT -o compat=0.10,lazy_refcounts=on "$TEST_IMG" 64M + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/050 b/tests/qemu-iotests/050 +index 05793e2..07802bc 100755 +--- a/tests/qemu-iotests/050 ++++ b/tests/qemu-iotests/050 +@@ -31,8 +31,8 @@ status=1 # failure is the default! + _cleanup() + { + _cleanup_test_img +- rm -f $TEST_IMG.old +- rm -f $TEST_IMG.new ++ rm -f "$TEST_IMG.old" ++ rm -f "$TEST_IMG.new" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -53,21 +53,21 @@ echo "== Creating images ==" + + size=10M + _make_test_img $size +-$QEMU_IO -c "write -P 0x40 0 1048576" $TEST_IMG | _filter_qemu_io +-mv $TEST_IMG $TEST_IMG.old ++$QEMU_IO -c "write -P 0x40 0 1048576" "$TEST_IMG" | _filter_qemu_io ++mv "$TEST_IMG" "$TEST_IMG.old" + + _make_test_img $size +-$QEMU_IO -c "write -P 0x5a 0 1048576" $TEST_IMG | _filter_qemu_io +-mv $TEST_IMG $TEST_IMG.new ++$QEMU_IO -c "write -P 0x5a 0 1048576" "$TEST_IMG" | _filter_qemu_io ++mv "$TEST_IMG" "$TEST_IMG.new" + +-_make_test_img -b $TEST_IMG.old $size +-$QEMU_IO -c "write -z 0 1048576" $TEST_IMG | _filter_qemu_io ++_make_test_img -b "$TEST_IMG.old" $size ++$QEMU_IO -c "write -z 0 1048576" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== Rebasing the image ==" + +-$QEMU_IMG rebase -b $TEST_IMG.new $TEST_IMG +-$QEMU_IO -c "read -P 0x00 0 1048576" $TEST_IMG | _filter_qemu_io ++$QEMU_IMG rebase -b "$TEST_IMG.new" "$TEST_IMG" ++$QEMU_IO -c "read -P 0x00 0 1048576" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 +index 93a2797..b8775b6 100755 +--- a/tests/qemu-iotests/051 ++++ b/tests/qemu-iotests/051 +@@ -62,21 +62,21 @@ echo + echo === Unknown option === + echo + +-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt= +-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=on +-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=1234 +-run_qemu -drive file=$TEST_IMG,format=qcow2,unknown_opt=foo ++run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt= ++run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=on ++run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234 ++run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo + + + echo + echo === Enable and disable lazy refcounting on the command line, plus some invalid values === + echo + +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts= +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=42 +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=foo ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts= ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=42 ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=foo + + + echo +@@ -85,8 +85,8 @@ echo + + _make_test_img -ocompat=0.10 $size + +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on +-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=on ++run_qemu -drive file="$TEST_IMG",format=qcow2,lazy-refcounts=off + + echo + echo === No medium === +@@ -112,21 +112,21 @@ echo + echo === Read-only === + echo + +-run_qemu -drive file=$TEST_IMG,if=floppy,readonly=on +-run_qemu -drive file=$TEST_IMG,if=ide,media=cdrom,readonly=on +-#run_qemu -drive file=$TEST_IMG,if=scsi,media=cdrom,readonly=on ++run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on ++run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on ++#run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on + +-run_qemu -drive file=$TEST_IMG,if=ide,readonly=on +-run_qemu -drive file=$TEST_IMG,if=virtio,readonly=on +-#run_qemu -drive file=$TEST_IMG,if=scsi,readonly=on ++run_qemu -drive file="$TEST_IMG",if=ide,readonly=on ++run_qemu -drive file="$TEST_IMG",if=virtio,readonly=on ++#run_qemu -drive file="$TEST_IMG",if=scsi,readonly=on + +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-cd,drive=disk +-#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk ++run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk ++#run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk + +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-drive,drive=disk +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-hd,drive=disk +-#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +-#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk ++run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk ++run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk ++#run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk ++#run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk + + echo + echo === Cache modes === +@@ -146,8 +146,8 @@ echo + echo === Specifying the protocol layer === + echo + +-run_qemu -drive file=$TEST_IMG,file.driver=file +-run_qemu -drive file=$TEST_IMG,file.driver=qcow2 ++run_qemu -drive file="$TEST_IMG",file.driver=file ++run_qemu -drive file="$TEST_IMG",file.driver=qcow2 + + echo + echo === Parsing protocol from file name === +diff --git a/tests/qemu-iotests/052 b/tests/qemu-iotests/052 +index 14a5126..f955b69 100755 +--- a/tests/qemu-iotests/052 ++++ b/tests/qemu-iotests/052 +@@ -48,12 +48,12 @@ _make_test_img $size + + echo + echo "== reading whole image ==" +-$QEMU_IO -s -c "read 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -s -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io + + echo + echo "== writing whole image does not modify image ==" +-$QEMU_IO -s -c "write -P 0xa 0 $size" $TEST_IMG | _filter_qemu_io +-$QEMU_IO -c "read -P 0 0 $size" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -s -c "write -P 0xa 0 $size" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IO -c "read -P 0 0 $size" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/053 b/tests/qemu-iotests/053 +index bc56992..e589e5f 100755 +--- a/tests/qemu-iotests/053 ++++ b/tests/qemu-iotests/053 +@@ -30,7 +30,7 @@ status=1 # failure is the default! + + _cleanup() + { +- rm -f $TEST_IMG.orig ++ rm -f "$TEST_IMG.orig" + _cleanup_test_img + } + trap "_cleanup; exit \$status" 0 1 2 3 15 +@@ -47,13 +47,13 @@ echo + echo "== Creating single sector image ==" + + _make_test_img 512 +-$QEMU_IO -c "write -P0xa 0 512" $TEST_IMG | _filter_qemu_io +-mv $TEST_IMG $TEST_IMG.orig ++$QEMU_IO -c "write -P0xa 0 512" "$TEST_IMG" | _filter_qemu_io ++mv "$TEST_IMG" "$TEST_IMG.orig" + + echo + echo "== Converting the image, compressed ==" + +-$QEMU_IMG convert -c -O $IMGFMT $TEST_IMG.orig $TEST_IMG ++$QEMU_IMG convert -c -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG" + _check_test_img + + echo +@@ -64,7 +64,7 @@ _img_info | grep '^virtual size:' + echo + echo "== Verifying the compressed image ==" + +-$QEMU_IO -c "read -P0xa 0 512" $TEST_IMG | _filter_qemu_io ++$QEMU_IO -c "read -P0xa 0 512" "$TEST_IMG" | _filter_qemu_io + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/054 b/tests/qemu-iotests/054 +index b360429..5a0d1b1 100755 +--- a/tests/qemu-iotests/054 ++++ b/tests/qemu-iotests/054 +@@ -49,7 +49,7 @@ _make_test_img $((1024*1024))T + echo + echo "creating too large image (1 EB) using qcow2.py" + _make_test_img 4G +-./qcow2.py $TEST_IMG set-header size $((1024 ** 6)) ++./qcow2.py "$TEST_IMG" set-header size $((1024 ** 6)) + _check_test_img + + # success, all done +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index d2b3f9e..dd6addf 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -51,20 +51,20 @@ echo "=== Testing invalid granularity ===" + echo + _make_test_img 64M + poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff" +-{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + + echo "=== Testing too big L2 table size ===" + echo + _make_test_img 64M + poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff" +-{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + + echo "=== Testing too big L1 table size ===" + echo + _make_test_img 64M + poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff" + poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00" +-{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++{ $QEMU_IO -c "read 0 512" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir + + echo "=== Testing monolithicFlat creation and opening ===" + echo +diff --git a/tests/qemu-iotests/063 b/tests/qemu-iotests/063 +index de0cbbd..2ab8f20 100644 +--- a/tests/qemu-iotests/063 ++++ b/tests/qemu-iotests/063 +@@ -32,7 +32,7 @@ status=1 # failure is the default! + _cleanup() + { + _cleanup_test_img +- rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2 ++ rm -f "$TEST_IMG.orig" "$TEST_IMG.raw" "$TEST_IMG.raw2" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -49,47 +49,47 @@ _make_test_img 4M + + echo "== Testing conversion with -n fails with no target file ==" + # check .orig file does not exist +-rm -f $TEST_IMG.orig +-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig >/dev/null 2>&1; then ++rm -f "$TEST_IMG.orig" ++if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" >/dev/null 2>&1; then + exit 1 + fi + + echo "== Testing conversion with -n succeeds with a target file ==" +-rm -f $TEST_IMG.orig +-cp $TEST_IMG $TEST_IMG.orig +-if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG $TEST_IMG.orig ; then ++rm -f "$TEST_IMG.orig" ++cp "$TEST_IMG" "$TEST_IMG.orig" ++if ! $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG" "$TEST_IMG.orig" ; then + exit 1 + fi + + echo "== Testing conversion to raw is the same after conversion with -n ==" + # compare the raw files +-if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG $TEST_IMG.raw1 ; then ++if ! $QEMU_IMG convert -f $IMGFMT -O raw "$TEST_IMG" "$TEST_IMG.raw1" ; then + exit 1 + fi + +-if ! $QEMU_IMG convert -f $IMGFMT -O raw $TEST_IMG.orig $TEST_IMG.raw2 ; then ++if ! $QEMU_IMG convert -f $IMGFMT -O raw "$TEST_IMG.orig" "$TEST_IMG.raw2" ; then + exit 1 + fi + +-if ! cmp $TEST_IMG.raw1 $TEST_IMG.raw2 ; then ++if ! cmp "$TEST_IMG.raw1" "$TEST_IMG.raw2" ; then + exit 1 + fi + + echo "== Testing conversion back to original format ==" +-if ! $QEMU_IMG convert -f raw -O $IMGFMT -n $TEST_IMG.raw2 $TEST_IMG ; then ++if ! $QEMU_IMG convert -f raw -O $IMGFMT -n "$TEST_IMG.raw2" "$TEST_IMG" ; then + exit 1 + fi + _check_test_img + + echo "== Testing conversion to a smaller file fails ==" +-rm -f $TEST_IMG.orig +-mv $TEST_IMG $TEST_IMG.orig ++rm -f "$TEST_IMG.orig" ++mv "$TEST_IMG" "$TEST_IMG.orig" + _make_test_img 2M +-if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n $TEST_IMG.orig $TEST_IMG >/dev/null 2>&1; then ++if $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n "$TEST_IMG.orig" "$TEST_IMG" >/dev/null 2>&1; then + exit 1 + fi + +-rm -f $TEST_IMG.orig $TEST_IMG.raw $TEST_IMG.raw2 ++rm -f "$TEST_IMG.orig" "$TEST_IMG.raw" "$TEST_IMG.raw2" + + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 6730955..1b22db0 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -164,12 +164,12 @@ _cleanup_test_img() + + nbd) + kill $QEMU_NBD_PID +- rm -f $TEST_IMG_FILE ++ rm -f "$TEST_IMG_FILE" + ;; + file) +- rm -f $TEST_DIR/t.$IMGFMT +- rm -f $TEST_DIR/t.$IMGFMT.orig +- rm -f $TEST_DIR/t.$IMGFMT.base ++ rm -f "$TEST_DIR/t.$IMGFMT" ++ rm -f "$TEST_DIR/t.$IMGFMT.orig" ++ rm -f "$TEST_DIR/t.$IMGFMT.base" + if [ -n "$SAMPLE_IMG_FILE" ] + then + rm -f "$TEST_DIR/$SAMPLE_IMG_FILE" +@@ -177,11 +177,11 @@ _cleanup_test_img() + ;; + + rbd) +- rbd rm $TEST_DIR/t.$IMGFMT > /dev/null ++ rbd rm "$TEST_DIR/t.$IMGFMT" > /dev/null + ;; + + sheepdog) +- collie vdi delete $TEST_DIR/t.$IMGFMT ++ collie vdi delete "$TEST_DIR/t.$IMGFMT" + ;; + + esac +@@ -189,7 +189,7 @@ _cleanup_test_img() + + _check_test_img() + { +- $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | _filter_testdir | \ ++ $QEMU_IMG check "$@" -f $IMGFMT "$TEST_IMG" 2>&1 | _filter_testdir | \ + sed -e '/allocated.*fragmented.*compressed clusters/d' \ + -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \ + -e '/Image end offset: [0-9]\+/d' +@@ -197,7 +197,7 @@ _check_test_img() + + _img_info() + { +- $QEMU_IMG info "$@" $TEST_IMG 2>&1 | \ ++ $QEMU_IMG info "$@" "$TEST_IMG" 2>&1 | \ + sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Remove-lsi53c895a-tests-from-051.patch b/SOURCES/kvm-qemu-iotests-Remove-lsi53c895a-tests-from-051.patch new file mode 100644 index 0000000..77e5d95 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Remove-lsi53c895a-tests-from-051.patch @@ -0,0 +1,184 @@ +From 9dcde11f25f85804f31d00fc45eed16595aebeec Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 18 Sep 2013 10:31:44 +0200 +Subject: [PATCH 38/38] qemu-iotests: Remove lsi53c895a tests from 051 + +Message-id: <1379499002-5231-7-git-send-email-mreitz@redhat.com> +Patchwork-id: 54437 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 6/6] qemu-iotests: Remove lsi53c895a tests from 051 +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 +Upstream: N/A, RHEL-only + +LSI SCSI is disabled in RHEL7, the corresponding checks in 051 are +therefore bound to fail. This patch removes these checks and their +expected output from test 051. + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/051 | 20 +++++++++--------- + tests/qemu-iotests/051.out | 47 -------------------------------------------- + 2 files changed, 10 insertions(+), 57 deletions(-) + +diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 +index 1f39c6a..93a2797 100755 +--- a/tests/qemu-iotests/051 ++++ b/tests/qemu-iotests/051 +@@ -94,19 +94,19 @@ echo + + run_qemu -drive if=floppy + run_qemu -drive if=ide,media=cdrom +-run_qemu -drive if=scsi,media=cdrom ++#run_qemu -drive if=scsi,media=cdrom + + run_qemu -drive if=ide + run_qemu -drive if=virtio +-run_qemu -drive if=scsi ++#run_qemu -drive if=scsi + + run_qemu -drive if=none,id=disk -device ide-cd,drive=disk +-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk ++#run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk + + run_qemu -drive if=none,id=disk -device ide-drive,drive=disk + run_qemu -drive if=none,id=disk -device ide-hd,drive=disk +-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk ++#run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk ++#run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk + + echo + echo === Read-only === +@@ -114,19 +114,19 @@ echo + + run_qemu -drive file=$TEST_IMG,if=floppy,readonly=on + run_qemu -drive file=$TEST_IMG,if=ide,media=cdrom,readonly=on +-run_qemu -drive file=$TEST_IMG,if=scsi,media=cdrom,readonly=on ++#run_qemu -drive file=$TEST_IMG,if=scsi,media=cdrom,readonly=on + + run_qemu -drive file=$TEST_IMG,if=ide,readonly=on + run_qemu -drive file=$TEST_IMG,if=virtio,readonly=on +-run_qemu -drive file=$TEST_IMG,if=scsi,readonly=on ++#run_qemu -drive file=$TEST_IMG,if=scsi,readonly=on + + run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-cd,drive=disk +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk ++#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk + + run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-drive,drive=disk + run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device ide-hd,drive=disk +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +-run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk ++#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk ++#run_qemu -drive file=$TEST_IMG,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk + + echo + echo === Cache modes === +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 5582ed3..e3cf244 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -65,10 +65,6 @@ Testing: -drive if=ide,media=cdrom + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive if=scsi,media=cdrom +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + Testing: -drive if=ide + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: Device needs media, but drive is empty +@@ -82,21 +78,10 @@ QEMU_PROG: -drive if=virtio: Device initialization failed. + QEMU_PROG: -drive if=virtio: Device initialization failed. + QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized + +-Testing: -drive if=scsi +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty +-QEMU_PROG: -drive if=scsi: Device initialization failed. +-QEMU_PROG: Device initialization failed. +-QEMU_PROG: Initialization of device lsi53c895a failed +- + Testing: -drive if=none,id=disk -device ide-cd,drive=disk + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + Testing: -drive if=none,id=disk -device ide-drive,drive=disk + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +@@ -109,18 +94,6 @@ QEMU X.Y.Z monitor - type 'help' for more information + QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + +-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +-QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. +-QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized +- +-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +-QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. +-QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized +- + + === Read-only === + +@@ -132,10 +105,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type + +@@ -143,18 +112,10 @@ Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + +-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk + QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +@@ -167,14 +128,6 @@ QEMU X.Y.Z monitor - type 'help' for more information + QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + +-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- +-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +-QEMU X.Y.Z monitor - type 'help' for more information +-(qemu) qququiquit +- + + === Cache modes === + +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Test-for-loading-VM-state-from-qcow2.patch b/SOURCES/kvm-qemu-iotests-Test-for-loading-VM-state-from-qcow2.patch new file mode 100644 index 0000000..1582116 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Test-for-loading-VM-state-from-qcow2.patch @@ -0,0 +1,147 @@ +From 50513a8391e05285c27241e1cf781ff1370972bf Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 1 Nov 2013 14:23:17 +0100 +Subject: [PATCH 29/81] qemu-iotests: Test for loading VM state from qcow2 + +RH-Author: Max Reitz +Message-id: <1383315797-30938-4-git-send-email-mreitz@redhat.com> +Patchwork-id: 55218 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 3/3] qemu-iotests: Test for loading VM state from qcow2 +Bugzilla: 1025740 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Alex Williamson + +BZ: 1025740 + +Add a test for saving a VM state from a qcow2 image and loading it back +(with having restarted qemu in between); this should work without any +problems. + +Signed-off-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit ab6f2bbb2871db8a7ed2457328e864cdf2e2fc82) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/group + +Conflicts because upstream contains more test in the group file. +--- + tests/qemu-iotests/068 | 65 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/068.out | 11 ++++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 77 insertions(+) + create mode 100755 tests/qemu-iotests/068 + create mode 100644 tests/qemu-iotests/068.out + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/068 | 65 ++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/068.out | 11 +++++++ + tests/qemu-iotests/group | 1 + + 3 files changed, 77 insertions(+), 0 deletions(-) + create mode 100755 tests/qemu-iotests/068 + create mode 100644 tests/qemu-iotests/068.out + +diff --git a/tests/qemu-iotests/068 b/tests/qemu-iotests/068 +new file mode 100755 +index 0000000..b72e555 +--- /dev/null ++++ b/tests/qemu-iotests/068 +@@ -0,0 +1,65 @@ ++#!/bin/bash ++# ++# Test case for loading a saved VM state from a qcow2 image ++# ++# Copyright (C) 2013 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 generic ++_supported_os Linux ++ ++IMGOPTS="compat=1.1" ++IMG_SIZE=128K ++ ++echo ++echo "=== Saving and reloading a VM state to/from a qcow2 image ===" ++echo ++_make_test_img $IMG_SIZE ++# Give qemu some time to boot before saving the VM state ++bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\ ++ $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\ ++ _filter_qemu ++# Now try to continue from that VM state (this should just work) ++echo quit |\ ++ $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\ ++ _filter_qemu ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/068.out b/tests/qemu-iotests/068.out +new file mode 100644 +index 0000000..abe35a9 +--- /dev/null ++++ b/tests/qemu-iotests/068.out +@@ -0,0 +1,11 @@ ++QA output created by 068 ++ ++=== Saving and reloading a VM state to/from a qcow2 image === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) ssasavsavesavevsavevmsavevm savevm 0 ++(qemu) qququiquit ++QEMU X.Y.Z monitor - type 'help' for more information ++(qemu) qququiquit ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 3b1d042..1017a19 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -61,3 +61,4 @@ + 052 rw auto backing + 053 rw auto + 059 rw auto ++068 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Try-creating-huge-qcow2-image.patch b/SOURCES/kvm-qemu-iotests-Try-creating-huge-qcow2-image.patch new file mode 100644 index 0000000..572478e --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Try-creating-huge-qcow2-image.patch @@ -0,0 +1,157 @@ +From 72620f05ee7306dcdd209e0e527b7a4c92bcb98d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:24 +0100 +Subject: [PATCH 67/87] qemu-iotests: Try creating huge qcow2 image + +RH-Author: Max Reitz +Message-id: <1383756824-6921-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 55556 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 01/21] qemu-iotests: Try creating huge qcow2 image +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Kevin Wolf + +BZ: 980771 + +It's supposed to fail gracefully instead of segfaulting. + +Signed-off-by: Kevin Wolf +(cherry picked from commit bd91ecbf5b43b52321c4d938e16a612b9c68bf06) + +Signed-off-by: Max Reitz + +Conflicts: + tests/qemu-iotests/group + +Conflicts because downstream contains more patches in the group file +than upstream did at the time this patch was originally written. +--- + tests/qemu-iotests/054 | 58 ++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/054.out | 10 ++++++++ + tests/qemu-iotests/common.rc | 2 +- + tests/qemu-iotests/group | 1 + + 4 files changed, 70 insertions(+), 1 deletion(-) + create mode 100755 tests/qemu-iotests/054 + create mode 100644 tests/qemu-iotests/054.out + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/054 | 58 ++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/054.out | 10 +++++++ + tests/qemu-iotests/common.rc | 2 +- + tests/qemu-iotests/group | 1 + + 4 files changed, 70 insertions(+), 1 deletions(-) + create mode 100755 tests/qemu-iotests/054 + create mode 100644 tests/qemu-iotests/054.out + +diff --git a/tests/qemu-iotests/054 b/tests/qemu-iotests/054 +new file mode 100755 +index 0000000..b360429 +--- /dev/null ++++ b/tests/qemu-iotests/054 +@@ -0,0 +1,58 @@ ++#!/bin/bash ++# ++# Test huge qcow2 images ++# ++# Copyright (C) 2013 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 ++ ++echo ++echo "creating too large image (1 EB)" ++_make_test_img $((1024*1024))T ++ ++echo ++echo "creating too large image (1 EB) using qcow2.py" ++_make_test_img 4G ++./qcow2.py $TEST_IMG set-header size $((1024 ** 6)) ++_check_test_img ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/054.out b/tests/qemu-iotests/054.out +new file mode 100644 +index 0000000..0b2fe30 +--- /dev/null ++++ b/tests/qemu-iotests/054.out +@@ -0,0 +1,10 @@ ++QA output created by 054 ++ ++creating too large image (1 EB) ++qemu-img: The image size is too large for file format 'qcow2' ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1152921504606846976 ++ ++creating too large image (1 EB) using qcow2.py ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 ++qemu-img: Could not open 'TEST_DIR/t.qcow2': File too large ++*** done +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 764a3eb..28b39e4 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -173,7 +173,7 @@ _cleanup_test_img() + + _check_test_img() + { +- $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | \ ++ $QEMU_IMG check "$@" -f $IMGFMT $TEST_IMG 2>&1 | _filter_testdir | \ + sed -e '/allocated.*fragmented.*compressed clusters/d' \ + -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \ + -e '/Image end offset: [0-9]\+/d' +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index c841c5e..d02ee96 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -60,6 +60,7 @@ + 051 rw auto + 052 rw auto backing + 053 rw auto ++054 rw auto + 059 rw auto + 060 rw auto + 063 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Update-051-reference-output.patch b/SOURCES/kvm-qemu-iotests-Update-051-reference-output.patch new file mode 100644 index 0000000..2fb4f21 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Update-051-reference-output.patch @@ -0,0 +1,253 @@ +From b63711901e9e01f780e0b4be99bac6009e795b68 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 10 Jul 2013 17:30:26 +0200 +Subject: [PATCH 29/38] qemu-iotests: Update 051 reference output + +Message-id: <1378736903-18489-30-git-send-email-kwolf@redhat.com> +Patchwork-id: 54216 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 29/32] qemu-iotests: Update 051 reference output +Bugzilla: 1005818 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1005818 + +This has been broken by commit bd5c51ee. + +Signed-off-by: Kevin Wolf +(cherry picked from commit 7a370406bdd13b1d46230d1cbca308d984d0dcae) + +Signed-off-by: Kevin Wolf +--- + tests/qemu-iotests/051.out | 107 ++++++++++++++++++++++++++----------- + tests/qemu-iotests/common.filter | 2 +- + 2 files changed, 76 insertions(+), 33 deletions(-) + +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 6b3d636..95ff245 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -23,10 +23,12 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not + === Enable and disable lazy refcounting on the command line, plus some invalid values === + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts= + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: Parameter 'lazy_refcounts' expects 'on' or 'off' +@@ -49,112 +51,152 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy ref + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + + === No medium === + + Testing: -drive if=floppy +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive if=ide,media=cdrom +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive if=scsi,media=cdrom +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive if=ide +-QEMU_PROG: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: Device needs media, but drive is empty ++QEMU_PROG: Device initialization failed. + QEMU_PROG: Initialization of device ide-hd failed + + Testing: -drive if=virtio +-QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty ++QEMU_PROG: -drive if=virtio: Device initialization failed. ++QEMU_PROG: -drive if=virtio: Device initialization failed. + QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized + + Testing: -drive if=scsi +-QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty ++QEMU_PROG: -drive if=scsi: Device initialization failed. ++QEMU_PROG: Device initialization failed. + QEMU_PROG: Initialization of device lsi53c895a failed + + Testing: -drive if=none,id=disk -device ide-cd,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive if=none,id=disk -device ide-drive,drive=disk +-QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty ++QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized + + Testing: -drive if=none,id=disk -device ide-hd,drive=disk +-QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty ++QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +-QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty ++QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. + QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +-QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty ++QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized + + + === Read-only === + + Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type + + Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk +-QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive ++QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk +-QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive ++QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + + === Cache modes === + + Testing: -drive media=cdrom,cache=none +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive media=cdrom,cache=directsync +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive media=cdrom,cache=writeback +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive media=cdrom,cache=writethrough +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive media=cdrom,cache=unsafe +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive media=cdrom,cache=invalid_value + QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option +@@ -163,7 +205,8 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option + === Specifying the protocol layer === + + Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file +-qququiquit ++QEMU 1.5.50 monitor - type 'help' for more information ++(qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index dcf6391..9dbcae8 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -155,7 +155,7 @@ _filter_qemu_io() + # replace occurrences of QEMU_PROG with "qemu" + _filter_qemu() + { +- sed -e "s#^$(basename $QEMU_PROG):#QEMU_PROG:#" ++ sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" + } + + # make sure this script returns success +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-Whitespace-cleanup.patch b/SOURCES/kvm-qemu-iotests-Whitespace-cleanup.patch new file mode 100644 index 0000000..d8f95c0 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Whitespace-cleanup.patch @@ -0,0 +1,1110 @@ +From 092e23e82636cf8a114688523d060f96d4e36eef Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 4 Sep 2013 13:16:04 +0200 +Subject: [PATCH 35/38] qemu-iotests: Whitespace cleanup + +Message-id: <1379499002-5231-4-git-send-email-mreitz@redhat.com> +Patchwork-id: 54434 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 3/6] qemu-iotests: Whitespace cleanup +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 + +These scripts used to have a four characters indentation, with eight +consecutive spaces converted into a tab. Convert everything into spaces. + +Signed-off-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 79e40ab10e1f4450c11ab8430cb2547146ded639) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/check | 234 ++++++++++---------- + tests/qemu-iotests/common | 422 ++++++++++++++++++------------------ + tests/qemu-iotests/common.config | 6 +- + tests/qemu-iotests/common.filter | 42 ++-- + tests/qemu-iotests/common.pattern | 4 +- + tests/qemu-iotests/common.rc | 92 ++++---- + 6 files changed, 400 insertions(+), 400 deletions(-) + +diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check +index 74628ae..e51bae8 100755 +--- a/tests/qemu-iotests/check ++++ b/tests/qemu-iotests/check +@@ -78,50 +78,50 @@ _wrapup() + + if $showme + then +- : ++ : + elif $needwrap + then +- if [ -f check.time -a -f $tmp.time ] +- then +- cat check.time $tmp.time \ +- | $AWK_PROG ' +- { t[$1] = $2 } +-END { if (NR > 0) { +- for (i in t) print i " " t[i] +- } +- }' \ +- | sort -n >$tmp.out +- mv $tmp.out check.time +- fi +- +- if [ -f $tmp.expunged ] +- then +- notrun=`wc -l <$tmp.expunged | sed -e 's/ *//g'` +- try=`expr $try - $notrun` +- list=`echo "$list" | sed -f $tmp.expunged` +- fi +- +- echo "" >>check.log +- date >>check.log +- echo $list | fmt | sed -e 's/^/ /' >>check.log +- $interrupt && echo "Interrupted!" >>check.log +- +- if [ ! -z "$notrun" ] +- then +- echo "Not run:$notrun" +- echo "Not run:$notrun" >>check.log +- fi ++ if [ -f check.time -a -f $tmp.time ] ++ then ++ cat check.time $tmp.time \ ++ | $AWK_PROG ' ++ { t[$1] = $2 } ++END { if (NR > 0) { ++ for (i in t) print i " " t[i] ++ } ++ }' \ ++ | sort -n >$tmp.out ++ mv $tmp.out check.time ++ fi ++ ++ if [ -f $tmp.expunged ] ++ then ++ notrun=`wc -l <$tmp.expunged | sed -e 's/ *//g'` ++ try=`expr $try - $notrun` ++ list=`echo "$list" | sed -f $tmp.expunged` ++ fi ++ ++ echo "" >>check.log ++ date >>check.log ++ echo $list | fmt | sed -e 's/^/ /' >>check.log ++ $interrupt && echo "Interrupted!" >>check.log ++ ++ if [ ! -z "$notrun" ] ++ then ++ echo "Not run:$notrun" ++ echo "Not run:$notrun" >>check.log ++ fi + if [ ! -z "$n_bad" -a $n_bad != 0 ] +- then +- echo "Failures:$bad" +- echo "Failed $n_bad of $try tests" +- echo "Failures:$bad" | fmt >>check.log +- echo "Failed $n_bad of $try tests" >>check.log +- else +- echo "Passed all $try tests" +- echo "Passed all $try tests" >>check.log +- fi +- needwrap=false ++ then ++ echo "Failures:$bad" ++ echo "Failed $n_bad of $try tests" ++ echo "Failures:$bad" | fmt >>check.log ++ echo "Failed $n_bad of $try tests" >>check.log ++ else ++ echo "Passed all $try tests" ++ echo "Passed all $try tests" >>check.log ++ fi ++ needwrap=false + fi + + rm -f /tmp/*.out /tmp/*.err /tmp/*.time +@@ -185,82 +185,82 @@ do + + if $showme + then +- echo +- continue +- elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null ++ echo ++ continue ++ elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null + then +- echo " - expunged" +- rm -f $seq.out.bad +- echo "/^$seq\$/d" >>$tmp.expunged ++ echo " - expunged" ++ rm -f $seq.out.bad ++ echo "/^$seq\$/d" >>$tmp.expunged + elif [ ! -f $seq ] + then +- echo " - no such test?" +- echo "/^$seq\$/d" >>$tmp.expunged ++ echo " - no such test?" ++ echo "/^$seq\$/d" >>$tmp.expunged + else +- # really going to try and run this one +- # +- rm -f $seq.out.bad +- lasttime=`sed -n -e "/^$seq /s/.* //p" /tmp/check.sts +- +- start=`_wallclock` +- $timestamp && echo -n " ["`date "+%T"`"]" +- [ ! -x $seq ] && chmod u+x $seq # ensure we can run it +- MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \ +- ./$seq >$tmp.out 2>&1 +- sts=$? +- $timestamp && _timestamp +- stop=`_wallclock` +- +- if [ -f core ] +- then +- echo -n " [dumped core]" +- mv core $seq.core +- err=true +- fi +- +- if [ -f $seq.notrun ] +- then +- $timestamp || echo -n " [not run] " +- $timestamp && echo " [not run]" && echo -n " $seq -- " +- cat $seq.notrun +- notrun="$notrun $seq" +- else +- if [ $sts -ne 0 ] +- then +- echo -n " [failed, exit status $sts]" +- err=true +- fi +- if [ ! -f $seq.out ] +- then +- echo " - no qualified output" +- err=true +- else +- if diff -w $seq.out $tmp.out >/dev/null 2>&1 +- then +- echo "" +- if $err +- then +- : +- else +- echo "$seq `expr $stop - $start`" >>$tmp.time +- fi +- else +- echo " - output mismatch (see $seq.out.bad)" +- mv $tmp.out $seq.out.bad +- $diff -w $seq.out $seq.out.bad +- err=true +- fi +- fi +- fi ++ # really going to try and run this one ++ # ++ rm -f $seq.out.bad ++ lasttime=`sed -n -e "/^$seq /s/.* //p" /tmp/check.sts ++ ++ start=`_wallclock` ++ $timestamp && echo -n " ["`date "+%T"`"]" ++ [ ! -x $seq ] && chmod u+x $seq # ensure we can run it ++ MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \ ++ ./$seq >$tmp.out 2>&1 ++ sts=$? ++ $timestamp && _timestamp ++ stop=`_wallclock` ++ ++ if [ -f core ] ++ then ++ echo -n " [dumped core]" ++ mv core $seq.core ++ err=true ++ fi ++ ++ if [ -f $seq.notrun ] ++ then ++ $timestamp || echo -n " [not run] " ++ $timestamp && echo " [not run]" && echo -n " $seq -- " ++ cat $seq.notrun ++ notrun="$notrun $seq" ++ else ++ if [ $sts -ne 0 ] ++ then ++ echo -n " [failed, exit status $sts]" ++ err=true ++ fi ++ if [ ! -f $seq.out ] ++ then ++ echo " - no qualified output" ++ err=true ++ else ++ if diff -w $seq.out $tmp.out >/dev/null 2>&1 ++ then ++ echo "" ++ if $err ++ then ++ : ++ else ++ echo "$seq `expr $stop - $start`" >>$tmp.time ++ fi ++ else ++ echo " - output mismatch (see $seq.out.bad)" ++ mv $tmp.out $seq.out.bad ++ $diff -w $seq.out $seq.out.bad ++ err=true ++ fi ++ fi ++ fi + + fi + +@@ -268,12 +268,12 @@ do + # + if $err + then +- bad="$bad $seq" +- n_bad=`expr $n_bad + 1` +- quick=false ++ bad="$bad $seq" ++ n_bad=`expr $n_bad + 1` ++ quick=false + fi + [ -f $seq.notrun ] || try=`expr $try + 1` +- ++ + seq="after_$seq" + done + +diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common +index 6826ea7..fecaf85 100644 +--- a/tests/qemu-iotests/common ++++ b/tests/qemu-iotests/common +@@ -54,58 +54,58 @@ do + + if $group + then +- # arg after -g +- group_list=`sed -n /dev/null +- then +- : +- else +- echo "$t" >>$tmp.list +- fi +- done +- group=false +- continue ++ if [ -z "$group_list" ] ++ then ++ echo "Group \"$r\" is empty or not defined?" ++ exit 1 ++ fi ++ [ ! -s $tmp.list ] && touch $tmp.list ++ for t in $group_list ++ do ++ if grep -s "^$t\$" $tmp.list >/dev/null ++ then ++ : ++ else ++ echo "$t" >>$tmp.list ++ fi ++ done ++ group=false ++ continue + + elif $xgroup + then +- # arg after -x +- [ ! -s $tmp.list ] && ls [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] >$tmp.list 2>/dev/null +- group_list=`sed -n $tmp.list 2>/dev/null ++ group_list=`sed -n $tmp.tmp +- mv $tmp.tmp $tmp.list +- numsed=0 +- rm -f $tmp.sed +- fi +- echo "/^$t\$/d" >>$tmp.sed +- numsed=`expr $numsed + 1` +- done +- sed -f $tmp.sed <$tmp.list >$tmp.tmp +- mv $tmp.tmp $tmp.list +- xgroup=false +- continue ++ if [ -z "$group_list" ] ++ then ++ echo "Group \"$r\" is empty or not defined?" ++ exit 1 ++ fi ++ numsed=0 ++ rm -f $tmp.sed ++ for t in $group_list ++ do ++ if [ $numsed -gt 100 ] ++ then ++ sed -f $tmp.sed <$tmp.list >$tmp.tmp ++ mv $tmp.tmp $tmp.list ++ numsed=0 ++ rm -f $tmp.sed ++ fi ++ echo "/^$t\$/d" >>$tmp.sed ++ numsed=`expr $numsed + 1` ++ done ++ sed -f $tmp.sed <$tmp.list >$tmp.tmp ++ mv $tmp.tmp $tmp.list ++ xgroup=false ++ continue + + elif $imgopts + then +@@ -119,11 +119,11 @@ s/ .*//p + case "$r" + in + +- -\? | -h | --help) # usage +- echo "Usage: $0 [options] [testlist]"' ++ -\? | -h | --help) # usage ++ echo "Usage: $0 [options] [testlist]"' + + common options +- -v verbose ++ -v verbose + + check options + -raw test raw (default) +@@ -138,162 +138,162 @@ check options + -sheepdog test sheepdog + -nbd test nbd + -ssh test ssh +- -xdiff graphical mode diff +- -nocache use O_DIRECT on backing file +- -misalign misalign memory allocations +- -n show me, do not run tests ++ -xdiff graphical mode diff ++ -nocache use O_DIRECT on backing file ++ -misalign misalign memory allocations ++ -n show me, do not run tests + -o options -o options to pass to qemu-img create/convert +- -T output timestamps +- -r randomize test order +- ++ -T output timestamps ++ -r randomize test order ++ + testlist options +- -g group[,group...] include tests from these groups +- -x group[,group...] exclude tests from these groups +- NNN include test NNN +- NNN-NNN include test range (eg. 012-021) ++ -g group[,group...] include tests from these groups ++ -x group[,group...] exclude tests from these groups ++ NNN include test NNN ++ NNN-NNN include test range (eg. 012-021) + ' +- exit 0 +- ;; +- +- -raw) +- IMGFMT=raw +- xpand=false +- ;; +- +- -cow) +- IMGFMT=cow +- xpand=false +- ;; +- +- -qcow) +- IMGFMT=qcow +- xpand=false +- ;; +- +- -qcow2) +- IMGFMT=qcow2 +- xpand=false +- ;; +- +- -qed) +- IMGFMT=qed +- xpand=false +- ;; +- +- -vdi) +- IMGFMT=vdi +- xpand=false +- ;; +- +- -vmdk) +- IMGFMT=vmdk +- xpand=false +- ;; +- +- -vpc) +- IMGFMT=vpc +- xpand=false +- ;; +- +- -rbd) +- IMGPROTO=rbd +- xpand=false +- ;; +- -sheepdog) +- IMGPROTO=sheepdog +- xpand=false +- ;; +- -nbd) +- IMGPROTO=nbd +- xpand=false +- ;; ++ exit 0 ++ ;; ++ ++ -raw) ++ IMGFMT=raw ++ xpand=false ++ ;; ++ ++ -cow) ++ IMGFMT=cow ++ xpand=false ++ ;; ++ ++ -qcow) ++ IMGFMT=qcow ++ xpand=false ++ ;; ++ ++ -qcow2) ++ IMGFMT=qcow2 ++ xpand=false ++ ;; ++ ++ -qed) ++ IMGFMT=qed ++ xpand=false ++ ;; ++ ++ -vdi) ++ IMGFMT=vdi ++ xpand=false ++ ;; ++ ++ -vmdk) ++ IMGFMT=vmdk ++ xpand=false ++ ;; ++ ++ -vpc) ++ IMGFMT=vpc ++ xpand=false ++ ;; ++ ++ -rbd) ++ IMGPROTO=rbd ++ xpand=false ++ ;; ++ -sheepdog) ++ IMGPROTO=sheepdog ++ xpand=false ++ ;; ++ -nbd) ++ IMGPROTO=nbd ++ xpand=false ++ ;; + -ssh) + IMGPROTO=ssh + xpand=false + ;; +- -nocache) +- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache" +- xpand=false +- ;; ++ -nocache) ++ QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --nocache" ++ xpand=false ++ ;; + +- -misalign) +- QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --misalign" +- xpand=false +- ;; ++ -misalign) ++ QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS --misalign" ++ xpand=false ++ ;; + + -valgrind) + valgrind=true +- xpand=false ++ xpand=false + ;; + +- -g) # -g group ... pick from group file +- group=true +- xpand=false +- ;; +- +- -xdiff) # graphical diff mode +- xpand=false +- +- if [ ! -z "$DISPLAY" ] +- then +- which xdiff >/dev/null 2>&1 && diff=xdiff +- which gdiff >/dev/null 2>&1 && diff=gdiff +- which tkdiff >/dev/null 2>&1 && diff=tkdiff +- which xxdiff >/dev/null 2>&1 && diff=xxdiff +- fi +- ;; +- +- -n) # show me, don't do it +- showme=true +- xpand=false +- ;; ++ -g) # -g group ... pick from group file ++ group=true ++ xpand=false ++ ;; ++ ++ -xdiff) # graphical diff mode ++ xpand=false ++ ++ if [ ! -z "$DISPLAY" ] ++ then ++ which xdiff >/dev/null 2>&1 && diff=xdiff ++ which gdiff >/dev/null 2>&1 && diff=gdiff ++ which tkdiff >/dev/null 2>&1 && diff=tkdiff ++ which xxdiff >/dev/null 2>&1 && diff=xxdiff ++ fi ++ ;; ++ ++ -n) # show me, don't do it ++ showme=true ++ xpand=false ++ ;; + -o) + imgopts=true + xpand=false + ;; +- -r) # randomize test order +- randomize=true +- xpand=false +- ;; +- +- -T) # turn on timestamp output +- timestamp=true +- xpand=false +- ;; +- +- -v) +- verbose=true +- xpand=false +- ;; +- -x) # -x group ... exclude from group file +- xgroup=true +- xpand=false +- ;; +- '[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]') +- echo "No tests?" +- status=1 +- exit $status +- ;; +- +- [0-9]*-[0-9]*) +- eval `echo $r | sed -e 's/^/start=/' -e 's/-/ end=/'` +- ;; +- +- [0-9]*-) +- eval `echo $r | sed -e 's/^/start=/' -e 's/-//'` +- end=`echo [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] | sed -e 's/\[0-9]//g' -e 's/ *$//' -e 's/.* //'` +- if [ -z "$end" ] +- then +- echo "No tests in range \"$r\"?" +- status=1 +- exit $status +- fi +- ;; +- +- *) +- start=$r +- end=$r +- ;; ++ -r) # randomize test order ++ randomize=true ++ xpand=false ++ ;; ++ ++ -T) # turn on timestamp output ++ timestamp=true ++ xpand=false ++ ;; ++ ++ -v) ++ verbose=true ++ xpand=false ++ ;; ++ -x) # -x group ... exclude from group file ++ xgroup=true ++ xpand=false ++ ;; ++ '[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]') ++ echo "No tests?" ++ status=1 ++ exit $status ++ ;; ++ ++ [0-9]*-[0-9]*) ++ eval `echo $r | sed -e 's/^/start=/' -e 's/-/ end=/'` ++ ;; ++ ++ [0-9]*-) ++ eval `echo $r | sed -e 's/^/start=/' -e 's/-//'` ++ end=`echo [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] | sed -e 's/\[0-9]//g' -e 's/ *$//' -e 's/.* //'` ++ if [ -z "$end" ] ++ then ++ echo "No tests in range \"$r\"?" ++ status=1 ++ exit $status ++ fi ++ ;; ++ ++ *) ++ start=$r ++ end=$r ++ ;; + + esac + +@@ -303,26 +303,26 @@ testlist options + + if $xpand + then +- have_test_arg=true +- $AWK_PROG /dev/null +- then +- # in group file ... OK +- echo $id >>$tmp.list +- else +- if [ -f expunged ] && $expunge && egrep "^$id([ ]|\$)" expunged >/dev/null +- then +- # expunged ... will be reported, but not run, later +- echo $id >>$tmp.list +- else +- # oops +- echo "$id - unknown test, ignored" +- fi +- fi +- done ++ have_test_arg=true ++ $AWK_PROG /dev/null ++ then ++ # in group file ... OK ++ echo $id >>$tmp.list ++ else ++ if [ -f expunged ] && $expunge && egrep "^$id([ ]|\$)" expunged >/dev/null ++ then ++ # expunged ... will be reported, but not run, later ++ echo $id >>$tmp.list ++ else ++ # oops ++ echo "$id - unknown test, ignored" ++ fi ++ fi ++ done + fi + + done +@@ -337,11 +337,11 @@ then + else + if $have_test_arg + then +- # had test numbers, but none in group file ... do nothing +- touch $tmp.list ++ # had test numbers, but none in group file ... do nothing ++ touch $tmp.list + else +- # no test numbers, do everything from group file +- sed -n -e '/^[0-9][0-9][0-9]*/s/[ ].*//p' $tmp.list ++ # no test numbers, do everything from group file ++ sed -n -e '/^[0-9][0-9][0-9]*/s/[ ].*//p' $tmp.list + fi + fi + +diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config +index 08a3f10..d794e62 100644 +--- a/tests/qemu-iotests/common.config ++++ b/tests/qemu-iotests/common.config +@@ -19,7 +19,7 @@ + # setup and check for config parameters, and in particular + # + # EMAIL - email of the script runner. +-# TEST_DIR - scratch test directory ++# TEST_DIR - scratch test directory + # + # - These can be added to $HOST_CONFIG_DIR (witch default to ./config) + # below or a separate local configuration file can be used (using +@@ -111,11 +111,11 @@ export QEMU_NBD=$QEMU_NBD_PROG + [ -f /etc/qemu-iotest.config ] && . /etc/qemu-iotest.config + + if [ -z "$TEST_DIR" ]; then +- TEST_DIR=`pwd`/scratch ++ TEST_DIR=`pwd`/scratch + fi + + if [ ! -e "$TEST_DIR" ]; then +- mkdir "$TEST_DIR" ++ mkdir "$TEST_DIR" + fi + + if [ ! -d "$TEST_DIR" ]; then +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 97a31ff..5dfda63 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -25,19 +25,19 @@ + # Outputs suitable message to stdout if it's not in range. + # + # A verbose option, -v, may be used as the LAST argument +-# +-# e.g. ++# ++# e.g. + # foo: 0.0298 = 0.03 +/- 5% +-# _within_tolerance "foo" 0.0298 0.03 5% +-# ++# _within_tolerance "foo" 0.0298 0.03 5% ++# + # foo: 0.0298 = 0.03 +/- 0.01 + # _within_tolerance "foo" 0.0298 0.03 0.01 + # + # foo: 0.0298 = 0.03 -0.01 +0.002 + # _within_tolerance "foo" 0.0298 0.03 0.01 0.002 + # +-# foo: verbose output of 0.0298 = 0.03 +/- 5% +-# _within_tolerance "foo" 0.0298 0.03 5% -v ++# foo: verbose output of 0.0298 = 0.03 +/- 5% ++# _within_tolerance "foo" 0.0298 0.03 5% -v + _within_tolerance() + { + _name=$1 +@@ -51,10 +51,10 @@ _within_tolerance() + # maxtol arg is optional + # verbose arg is optional + if [ $# -ge 5 ] +- then ++ then + if [ "$5" = "-v" ] + then +- _verbose=1 ++ _verbose=1 + else + _maxtol=$5 + fi +@@ -65,18 +65,18 @@ _within_tolerance() + fi + + # find min with or without % +- _mintolerance=`echo $_mintol | sed -e 's/%//'` ++ _mintolerance=`echo $_mintol | sed -e 's/%//'` + if [ $_mintol = $_mintolerance ] +- then ++ then + _min=`echo "scale=5; $_correct_val-$_mintolerance" | bc` + else + _min=`echo "scale=5; $_correct_val-$_mintolerance*0.01*$_correct_val" | bc` + fi + + # find max with or without % +- _maxtolerance=`echo $_maxtol | sed -e 's/%//'` ++ _maxtolerance=`echo $_maxtol | sed -e 's/%//'` + if [ $_maxtol = $_maxtolerance ] +- then ++ then + _max=`echo "scale=5; $_correct_val+$_maxtolerance" | bc` + else + _max=`echo "scale=5; $_correct_val+$_maxtolerance*0.01*$_correct_val" | bc` +@@ -88,7 +88,7 @@ _within_tolerance() + cat <$tmp.bc.1 + scale=5; + if ($_min <= $_given_val) 1; +-if ($_min > $_given_val) 0; ++if ($_min > $_given_val) 0; + EOF + + cat <$tmp.bc.2 +@@ -102,21 +102,21 @@ EOF + + rm -f $tmp.bc.[12] + +- _in_range=`expr $_above_min \& $_below_max` ++ _in_range=`expr $_above_min \& $_below_max` + + # fix up min, max precision for output + # can vary for 5.3, 6.2 + _min=`echo $_min | sed -e 's/0*$//'` # get rid of trailling zeroes + _max=`echo $_max | sed -e 's/0*$//'` # get rid of trailling zeroes + +- if [ $_in_range -eq 1 ] ++ if [ $_in_range -eq 1 ] + then +- [ $_verbose -eq 1 ] && echo $_name is in range +- return 0 ++ [ $_verbose -eq 1 ] && echo $_name is in range ++ return 0 + else +- [ $_verbose -eq 1 ] && echo $_name has value of $_given_val +- [ $_verbose -eq 1 ] && echo $_name is NOT in range $_min .. $_max +- return 1 ++ [ $_verbose -eq 1 ] && echo $_name has value of $_given_val ++ [ $_verbose -eq 1 ] && echo $_name is NOT in range $_min .. $_max ++ return 1 + fi + } + +@@ -125,7 +125,7 @@ EOF + _filter_date() + { + sed \ +- -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/' ++ -e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/' + } + + # replace occurrences of the actual TEST_DIR value with TEST_DIR +diff --git a/tests/qemu-iotests/common.pattern b/tests/qemu-iotests/common.pattern +index 85a40ee..00e0f60 100644 +--- a/tests/qemu-iotests/common.pattern ++++ b/tests/qemu-iotests/common.pattern +@@ -106,8 +106,8 @@ function io_test2() { + local num=$3 + + # Pattern (repeat after 9 clusters): +- # used - used - free - used - compressed - compressed - +- # free - free - compressed ++ # used - used - free - used - compressed - compressed - ++ # free - free - compressed + + # Write the clusters to be compressed + echo === Clusters to be compressed [1] +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 31eb62b..1e9b2f4 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -20,17 +20,17 @@ + dd() + { + if [ "$HOSTOS" == "Linux" ] +- then +- command dd --help | grep noxfer > /dev/null 2>&1 +- +- if [ "$?" -eq 0 ] +- then +- command dd status=noxfer $@ +- else +- command dd $@ +- fi ++ then ++ command dd --help | grep noxfer > /dev/null 2>&1 ++ ++ if [ "$?" -eq 0 ] ++ then ++ command dd status=noxfer $@ ++ else ++ command dd $@ ++ fi + else +- command dd $@ ++ command dd $@ + fi + } + +@@ -187,8 +187,8 @@ _get_pids_by_name() + { + if [ $# -ne 1 ] + then +- echo "Usage: _get_pids_by_name process-name" 1>&2 +- exit 1 ++ echo "Usage: _get_pids_by_name process-name" 1>&2 ++ exit 1 + fi + + # Algorithm ... all ps(1) variants have a time of the form MM:SS or +@@ -200,12 +200,12 @@ _get_pids_by_name() + + ps $PS_ALL_FLAGS \ + | sed -n \ +- -e 's/$/ /' \ +- -e 's/[ ][ ]*/ /g' \ +- -e 's/^ //' \ +- -e 's/^[^ ]* //' \ +- -e "/[0-9]:[0-9][0-9] *[^ ]*\/$1 /s/ .*//p" \ +- -e "/[0-9]:[0-9][0-9] *$1 /s/ .*//p" ++ -e 's/$/ /' \ ++ -e 's/[ ][ ]*/ /g' \ ++ -e 's/^ //' \ ++ -e 's/^[^ ]* //' \ ++ -e "/[0-9]:[0-9][0-9] *[^ ]*\/$1 /s/ .*//p" \ ++ -e "/[0-9]:[0-9][0-9] *$1 /s/ .*//p" + } + + # fqdn for localhost +@@ -223,8 +223,8 @@ _need_to_be_root() + id=`id | $SED_PROG -e 's/(.*//' -e 's/.*=//'` + if [ "$id" -ne 0 ] + then +- echo "Arrgh ... you need to be root (not uid=$id) to run this test" +- exit 1 ++ echo "Arrgh ... you need to be root (not uid=$id) to run this test" ++ exit 1 + fi + } + +@@ -242,33 +242,33 @@ _need_to_be_root() + _do() + { + if [ $# -eq 1 ]; then +- _cmd=$1 ++ _cmd=$1 + elif [ $# -eq 2 ]; then +- _note=$1 +- _cmd=$2 +- echo -n "$_note... " ++ _note=$1 ++ _cmd=$2 ++ echo -n "$_note... " + else +- echo "Usage: _do [note] cmd" 1>&2 +- status=1; exit ++ echo "Usage: _do [note] cmd" 1>&2 ++ status=1; exit + fi + + (eval "echo '---' \"$_cmd\"") >>$here/$seq.full + (eval "$_cmd") >$tmp._out 2>&1; ret=$? + cat $tmp._out >>$here/$seq.full + if [ $# -eq 2 ]; then +- if [ $ret -eq 0 ]; then +- echo "done" +- else +- echo "fail" +- fi ++ if [ $ret -eq 0 ]; then ++ echo "done" ++ else ++ echo "fail" ++ fi + fi + if [ $ret -ne 0 ] \ +- && [ "$_do_die_on_error" = "always" \ +- -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ] ++ && [ "$_do_die_on_error" = "always" \ ++ -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ] + then +- [ $# -ne 2 ] && echo +- eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full" +- status=1; exit ++ [ $# -ne 2 ] && echo ++ eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full" ++ status=1; exit + fi + + return $ret +@@ -299,9 +299,9 @@ _fail() + _supported_fmt() + { + for f; do +- if [ "$f" = "$IMGFMT" -o "$f" = "generic" ]; then +- return +- fi ++ if [ "$f" = "$IMGFMT" -o "$f" = "generic" ]; then ++ return ++ fi + done + + _notrun "not suitable for this image format: $IMGFMT" +@@ -312,9 +312,9 @@ _supported_fmt() + _supported_proto() + { + for f; do +- if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then +- return +- fi ++ if [ "$f" = "$IMGPROTO" -o "$f" = "generic" ]; then ++ return ++ fi + done + + _notrun "not suitable for this image protocol: $IMGPROTO" +@@ -326,10 +326,10 @@ _supported_os() + { + for h + do +- if [ "$h" = "$HOSTOS" ] +- then +- return +- fi ++ if [ "$h" = "$HOSTOS" ] ++ then ++ return ++ fi + done + + _notrun "not suitable for this OS: $HOSTOS" +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-add-empty-test-case-for-vmdk.patch b/SOURCES/kvm-qemu-iotests-add-empty-test-case-for-vmdk.patch new file mode 100644 index 0000000..d527d8b --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-add-empty-test-case-for-vmdk.patch @@ -0,0 +1,109 @@ +From c896fb12ce68b579e8954651db3d903600cf0f00 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:50 +0800 +Subject: [PATCH 04/13] qemu-iotests: add empty test case for vmdk + +Message-id: <1377573001-27070-5-git-send-email-famz@redhat.com> +Patchwork-id: 53784 +O-Subject: [RHEL-7 qemu-kvm PATCH 04/13] qemu-iotests: add empty test case for + vmdk +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +Will add vmdk specific tests later here. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit ca6cbb657d66a7beb70f9d91848c80d1a72b1674) +Signed-off-by: Fam Zheng + +Conflicts: + tests/qemu-iotests/group + Context conflict because some test scritps do not exist yet. +--- + tests/qemu-iotests/059 | 51 ++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/059.out | 2 + + tests/qemu-iotests/group | 1 + + 3 files changed, 54 insertions(+), 0 deletions(-) + create mode 100755 tests/qemu-iotests/059 + create mode 100644 tests/qemu-iotests/059.out + +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +new file mode 100755 +index 0000000..9dc7f64 +--- /dev/null ++++ b/tests/qemu-iotests/059 +@@ -0,0 +1,51 @@ ++#!/bin/bash ++# ++# Test case for vmdk ++# ++# Copyright (C) 2013 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=famz@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 vmdk-specific low-level functionality ++_supported_fmt vmdk ++_supported_proto generic ++_supported_os Linux ++ ++granularity_offset=16 ++ ++# success, all done ++echo "*** done" ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +new file mode 100644 +index 0000000..4ca7f29 +--- /dev/null ++++ b/tests/qemu-iotests/059.out +@@ -0,0 +1,2 @@ ++QA output created by 059 ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 68eabda..3b1d042 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -60,3 +60,4 @@ + 051 rw auto + 052 rw auto backing + 053 rw auto ++059 rw auto +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-add-monolithicFlat-creation-test-to-059.patch b/SOURCES/kvm-qemu-iotests-add-monolithicFlat-creation-test-to-059.patch new file mode 100644 index 0000000..f0a8d33 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-add-monolithicFlat-creation-test-to-059.patch @@ -0,0 +1,64 @@ +From 1e237fbebc414e23218350bdbb2b4f128f345800 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Wed, 9 Oct 2013 09:50:23 +0200 +Subject: [PATCH 11/11] qemu-iotests: add monolithicFlat creation test to 059 + +RH-Author: Fam Zheng +Message-id: <1381312223-7074-4-git-send-email-famz@redhat.com> +Patchwork-id: 54795 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/3] qemu-iotests: add monolithicFlat creation test to 059 +Bugzilla: 1017049 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 2fe2e2907163f6d86b6bbced776ec8f9319ca83f) +Signed-off-by: Fam Zheng +--- + tests/qemu-iotests/059 | 5 +++++ + tests/qemu-iotests/059.out | 7 +++++++ + 2 files changed, 12 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/059 | 5 +++++ + tests/qemu-iotests/059.out | 7 +++++++ + 2 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index b03429d..d2b3f9e 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -66,6 +66,11 @@ poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff" + poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00" + { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + ++echo "=== Testing monolithicFlat creation and opening ===" ++echo ++IMGOPTS="subformat=monolithicFlat" _make_test_img 2G ++$QEMU_IMG info $TEST_IMG | _filter_testdir ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 9e715e5..2a4c44d 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -17,4 +17,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + L1 size too big + qemu-io: can't open device TEST_DIR/t.vmdk + no file open, try 'help open' ++=== Testing monolithicFlat creation and opening === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 ++image: TEST_DIR/t.vmdk ++file format: vmdk ++virtual size: 2.0G (2147483648 bytes) ++disk size: 4.0K + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-add-poke_file-utility-function.patch b/SOURCES/kvm-qemu-iotests-add-poke_file-utility-function.patch new file mode 100644 index 0000000..fae94de --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-add-poke_file-utility-function.patch @@ -0,0 +1,45 @@ +From 43e2ea9a31c301e162507a3f656b8719454df086 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 6 Aug 2013 15:44:49 +0800 +Subject: [PATCH 03/13] qemu-iotests: add poke_file utility function + +Message-id: <1377573001-27070-4-git-send-email-famz@redhat.com> +Patchwork-id: 53783 +O-Subject: [RHEL-7 qemu-kvm PATCH 03/13] qemu-iotests: add poke_file utility function +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +The new poke_file function sets bytes at an offset in a file given a +printf-style format string. It can be used to corrupt an image file for +test coverage of error paths. + +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 23ea2ecc2a43d850bc9482068201ece5da36a448) +Signed-off-by: Fam Zheng +--- + tests/qemu-iotests/common.rc | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 1e9b2f4..1187b86 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -34,6 +34,12 @@ dd() + fi + } + ++# poke_file 'test.img' 512 '\xff\xfe' ++poke_file() ++{ ++ printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null ++} ++ + # we need common.config + if [ "$iam" != "check" ] + then +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-filter-QEMU-version-in-monitor-banner.patch b/SOURCES/kvm-qemu-iotests-filter-QEMU-version-in-monitor-banner.patch new file mode 100644 index 0000000..c2bdbee --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-filter-QEMU-version-in-monitor-banner.patch @@ -0,0 +1,252 @@ +From 61a448529ef5b2a2ad37e7f7ff5d858593abc9c6 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 5 Aug 2013 14:40:34 +0200 +Subject: [PATCH 33/38] qemu-iotests: filter QEMU version in monitor banner + +Message-id: <1379499002-5231-2-git-send-email-mreitz@redhat.com> +Patchwork-id: 54432 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 1/6] qemu-iotests: filter QEMU version in monitor banner +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 + +Filter out the QEMU monitor version banner so that tests do not break +when the QEMU version number is changed. + +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 9580498b9a599b38c3a28599dcd40bd59f12af2c) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/051.out | 64 +++++++++++++++++++------------------- + tests/qemu-iotests/common.filter | 3 +- + 2 files changed, 34 insertions(+), 33 deletions(-) + +diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out +index 9588d0c..5582ed3 100644 +--- a/tests/qemu-iotests/051.out ++++ b/tests/qemu-iotests/051.out +@@ -23,11 +23,11 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not + === Enable and disable lazy refcounting on the command line, plus some invalid values === + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts= +@@ -51,72 +51,72 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy ref + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument + + Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + + === No medium === + + Testing: -drive if=floppy +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive if=ide,media=cdrom +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive if=scsi,media=cdrom +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive if=ide +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: Device needs media, but drive is empty + QEMU_PROG: Device initialization failed. + QEMU_PROG: Initialization of device ide-hd failed + + Testing: -drive if=virtio +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty + QEMU_PROG: -drive if=virtio: Device initialization failed. + QEMU_PROG: -drive if=virtio: Device initialization failed. + QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized + + Testing: -drive if=scsi +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty + QEMU_PROG: -drive if=scsi: Device initialization failed. + QEMU_PROG: Device initialization failed. + QEMU_PROG: Initialization of device lsi53c895a failed + + Testing: -drive if=none,id=disk -device ide-cd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive if=none,id=disk -device ide-drive,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty + QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized + + Testing: -drive if=none,id=disk -device ide-hd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty + QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty + QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. + QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized + + Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty + QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized +@@ -125,77 +125,77 @@ QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized + === Read-only === + + Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type + + Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive + QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive + QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. + QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + + === Cache modes === + + Testing: -drive media=cdrom,cache=none +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive media=cdrom,cache=directsync +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive media=cdrom,cache=writeback +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive media=cdrom,cache=writethrough +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive media=cdrom,cache=unsafe +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive media=cdrom,cache=invalid_value +@@ -205,7 +205,7 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option + === Specifying the protocol layer === + + Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file +-QEMU 1.5.50 monitor - type 'help' for more information ++QEMU X.Y.Z monitor - type 'help' for more information + (qemu) qququiquit + + Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 9dbcae8..97a31ff 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -155,7 +155,8 @@ _filter_qemu_io() + # replace occurrences of QEMU_PROG with "qemu" + _filter_qemu() + { +- sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" ++ sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \ ++ -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#' + } + + # make sure this script returns success +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-iotests-fix-test-case-059.patch b/SOURCES/kvm-qemu-iotests-fix-test-case-059.patch new file mode 100644 index 0000000..9ba2e1c --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-fix-test-case-059.patch @@ -0,0 +1,65 @@ +From aefd8fc94d47366ba697967f3c9704dfeb5bee34 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:33 +0100 +Subject: [PATCH 76/87] qemu-iotests: fix test case 059 + +RH-Author: Max Reitz +Message-id: <1383756824-6921-11-git-send-email-mreitz@redhat.com> +Patchwork-id: 55565 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 10/21] qemu-iotests: fix test case 059 +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Since commit "block: Error parameter for open functions", error output +is more verbose. Update test case output file to follow the change. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit fc7ce63fb101ffb56027a04e89c8c6a38031bfc3) + +Signed-off-by: Max Reitz +--- + tests/qemu-iotests/059.out | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + tests/qemu-iotests/059.out | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 2a4c44d..9159dbe 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -3,19 +3,19 @@ QA output created by 059 + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + invalid granularity, image may be corrupt +-qemu-io: can't open device TEST_DIR/t.vmdk ++qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type + no file open, try 'help open' + === Testing too big L2 table size === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + L2 table size too big +-qemu-io: can't open device TEST_DIR/t.vmdk ++qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type + no file open, try 'help open' + === Testing too big L1 table size === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + L1 size too big +-qemu-io: can't open device TEST_DIR/t.vmdk ++qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type + no file open, try 'help open' + === Testing monolithicFlat creation and opening === + +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-option-Fix-qemu_opts_find-for-null-id-arguments.patch b/SOURCES/kvm-qemu-option-Fix-qemu_opts_find-for-null-id-arguments.patch new file mode 100644 index 0000000..a3f0e1d --- /dev/null +++ b/SOURCES/kvm-qemu-option-Fix-qemu_opts_find-for-null-id-arguments.patch @@ -0,0 +1,61 @@ +From e53520a7e7f2cf2f78786c6c1ae906e70c26fd7e Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:00 +0200 +Subject: [PATCH 07/28] qemu-option: Fix qemu_opts_find() for null id arguments + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-2-git-send-email-armbru@redhat.com> +Patchwork-id: 52992 +O-Subject: [PATCH 7.0 qemu-kvm 1/6] qemu-option: Fix qemu_opts_find() for null id arguments +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +Crashes when the first list member has an ID. Admittedly nonsensical +reproducer: + +$ qemu-system-x86_64 -nodefaults -machine id=foo -machine "" + +Signed-off-by: Markus Armbruster +Reviewed-by: Peter Maydell +Message-id: 1372943363-24081-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 96bc97ebf350ec480b69082819cedb8850f46a0f) +--- + util/qemu-option.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-option.c | 12 ++++-------- + 1 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 8b74bf1..b6d2ac0 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -736,16 +736,12 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id) + QemuOpts *opts; + + QTAILQ_FOREACH(opts, &list->head, next) { +- if (!opts->id) { +- if (!id) { +- return opts; +- } +- continue; ++ if (!opts->id && !id) { ++ return opts; + } +- if (strcmp(opts->id, id) != 0) { +- continue; ++ if (opts->id && id && !strcmp(opts->id, id)) { ++ return opts; + } +- return opts; + } + return NULL; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-option-Fix-qemu_opts_set_defaults-for-corner-ca.patch b/SOURCES/kvm-qemu-option-Fix-qemu_opts_set_defaults-for-corner-ca.patch new file mode 100644 index 0000000..1eda725 --- /dev/null +++ b/SOURCES/kvm-qemu-option-Fix-qemu_opts_set_defaults-for-corner-ca.patch @@ -0,0 +1,96 @@ +From c4ffa69bdec932cf674d92355967ce2876296893 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:01 +0200 +Subject: [PATCH 08/28] qemu-option: Fix qemu_opts_set_defaults() for corner cases + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-3-git-send-email-armbru@redhat.com> +Patchwork-id: 52990 +O-Subject: [PATCH 7.0 qemu-kvm 2/6] qemu-option: Fix qemu_opts_set_defaults() for corner cases +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +Commit 4f6dd9a changed the initialization of opts in opts_parse() to +this: + + if (defaults) { + if (!id && !QTAILQ_EMPTY(&list->head)) { + opts = qemu_opts_find(list, NULL); + } else { + opts = qemu_opts_create(list, id, 0); + } + } else { + opts = qemu_opts_create(list, id, 1); + } + +Same as before for !defaults. + +If defaults is true, and params has no ID, and options exist, we use +the first assignment. It sets opts to null if all options have an ID. +opts_parse() then returns null. qemu_opts_set_defaults() asserts the +value is non-null. It's the only caller that passes true for +defaults. + +To reproduce, try "-M xenpv -machine id=foo" (yes, "id=foo" is silly, +but it shouldn't crash). + +I believe the function attempts to do the following: + + If options don't yet exist, create new options + Else, if defaults, modify the existing options + Else, if list->merge_lists, modify the existing options + Else, fail + +A straightforward call of qemu_opts_create() does exactly that. + +Cc: Jan Kiszka +Signed-off-by: Markus Armbruster +Message-id: 1372943363-24081-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 6d4cd408686f5ae60b2b3b94b79f48ddedc2f39d) + +The upstream commit message's claim that a "straightforward call of +qemu_opts_create() does exactly that" is wrong. When +!list->merge_lists, and the option string doesn't contain id=, and +options without ID exist, then we don't actually modify the existing +options, we create new ones. + +Not reachable, because we never pass lists with !list->merge_lists to +qemu_opts_set_defaults(). + +Patch adding a suitable assertion pending upstream. +--- + util/qemu-option.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-option.c | 10 +--------- + 1 files changed, 1 insertions(+), 9 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index b6d2ac0..bdfbdb4 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -944,15 +944,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + get_opt_value(value, sizeof(value), p+4); + id = value; + } +- if (defaults) { +- if (!id && !QTAILQ_EMPTY(&list->head)) { +- opts = qemu_opts_find(list, NULL); +- } else { +- opts = qemu_opts_create(list, id, 0, &local_err); +- } +- } else { +- opts = qemu_opts_create(list, id, 1, &local_err); +- } ++ opts = qemu_opts_create(list, id, !defaults, &local_err); + if (opts == NULL) { + if (error_is_set(&local_err)) { + qerror_report_err(local_err); +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-option-check_params-is-now-unused-drop-it.patch b/SOURCES/kvm-qemu-option-check_params-is-now-unused-drop-it.patch new file mode 100644 index 0000000..2072736 --- /dev/null +++ b/SOURCES/kvm-qemu-option-check_params-is-now-unused-drop-it.patch @@ -0,0 +1,92 @@ +From 1d20e66fdee76ee9a7cab19de50a138588f0c8c8 Mon Sep 17 00:00:00 2001 +Message-Id: <1d20e66fdee76ee9a7cab19de50a138588f0c8c8.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:12 +0200 +Subject: [PATCH 02/14] qemu-option: check_params() is now unused, drop it + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-3-git-send-email-armbru@redhat.com> +Patchwork-id: 54559 +O-Subject: [PATCH 7.0 qemu-kvm 02/10] qemu-option: check_params() is now unused, drop it +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-3-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit a86b35f992f107323e432c0a96107e11e1b699ad) +--- + include/qemu/option.h | 2 -- + util/qemu-option.c | 30 ------------------------------ + 2 files changed, 32 deletions(-) + +Signed-off-by: Michal Novotny +--- + include/qemu/option.h | 2 -- + util/qemu-option.c | 30 ------------------------------ + 2 files changed, 32 deletions(-) + +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 9db74fb..13f5e72 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -55,8 +55,6 @@ int get_next_param_value(char *buf, int buf_size, + const char *tag, const char **pstr); + int get_param_value(char *buf, int buf_size, + const char *tag, const char *str); +-int check_params(char *buf, int buf_size, +- const char * const *params, const char *str); + + + /* +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 37e7640..5d686c8 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -123,36 +123,6 @@ int get_param_value(char *buf, int buf_size, + return get_next_param_value(buf, buf_size, tag, &str); + } + +-int check_params(char *buf, int buf_size, +- const char * const *params, const char *str) +-{ +- const char *p; +- int i; +- +- p = str; +- while (*p != '\0') { +- p = get_opt_name(buf, buf_size, p, '='); +- if (*p != '=') { +- return -1; +- } +- p++; +- for (i = 0; params[i] != NULL; i++) { +- if (!strcmp(params[i], buf)) { +- break; +- } +- } +- if (params[i] == NULL) { +- return -1; +- } +- p = get_opt_value(NULL, 0, p); +- if (*p != ',') { +- break; +- } +- p++; +- } +- return 0; +-} +- + /* + * Searches an option list for an option with the given name + */ +-- +1.7.11.7 + diff --git a/SOURCES/kvm-qemu-socket-catch-monitor_get_fd-failures.patch b/SOURCES/kvm-qemu-socket-catch-monitor_get_fd-failures.patch new file mode 100644 index 0000000..faed7d3 --- /dev/null +++ b/SOURCES/kvm-qemu-socket-catch-monitor_get_fd-failures.patch @@ -0,0 +1,43 @@ +From d24a791d6a9b4c316e666c95d676ceaf2f52198a Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:11 +0200 +Subject: [PATCH 04/18] qemu-socket: catch monitor_get_fd failures + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-4-git-send-email-kraxel@redhat.com> +Patchwork-id: 54862 +O-Subject: [RHEL-7 qemu-kvm PATCH 03/15] qemu-socket: catch monitor_get_fd failures +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit d1ec72a44e0a167f9e8254d6d1098d27f104571f) +--- + util/qemu-sockets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-sockets.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index 35023a8..126cbb6 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -903,7 +903,7 @@ int socket_connect(SocketAddress *addr, Error **errp, + + case SOCKET_ADDRESS_KIND_FD: + fd = monitor_get_fd(cur_mon, addr->fd->str, errp); +- if (callback) { ++ if (fd >= 0 && callback) { + qemu_set_nonblock(fd); + callback(fd, opaque); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-socket-don-t-leak-opts-on-error.patch b/SOURCES/kvm-qemu-socket-don-t-leak-opts-on-error.patch new file mode 100644 index 0000000..82adeb7 --- /dev/null +++ b/SOURCES/kvm-qemu-socket-don-t-leak-opts-on-error.patch @@ -0,0 +1,43 @@ +From ea210ca7017b87a1c7bf02050d6c60dcac17f54b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:22 +0200 +Subject: [PATCH 15/18] qemu-socket: don't leak opts on error + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-15-git-send-email-kraxel@redhat.com> +Patchwork-id: 54858 +O-Subject: [RHEL-7 qemu-kvm PATCH 14/15] qemu-socket: don't leak opts on error +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit 7a5b6af13a45ae7109900dee03a436819302126c) +--- + util/qemu-sockets.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-sockets.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index 126cbb6..095716e 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -963,7 +963,7 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp) + + default: + error_setg(errp, "socket type unsupported for datagram"); +- return -1; ++ fd = -1; + } + qemu_opts_del(opts); + return fd; +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-socket-drop-pointless-allocation.patch b/SOURCES/kvm-qemu-socket-drop-pointless-allocation.patch new file mode 100644 index 0000000..cf4a018 --- /dev/null +++ b/SOURCES/kvm-qemu-socket-drop-pointless-allocation.patch @@ -0,0 +1,42 @@ +From 6340a1e18aaaa236bb09680fdae5c5c58ec2a75b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:10 +0200 +Subject: [PATCH 03/18] qemu-socket: drop pointless allocation + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 54849 +O-Subject: [RHEL-7 qemu-kvm PATCH 02/15] qemu-socket: drop pointless allocation +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit c1204afc7c048cf58b0a8f1c11886f36ca73ef28) +--- + util/qemu-sockets.c | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-sockets.c | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index 86fb09c..35023a8 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -871,7 +871,6 @@ SocketAddress *socket_parse(const char *str, Error **errp) + } + } else { + addr->kind = SOCKET_ADDRESS_KIND_INET; +- addr->inet = g_new(InetSocketAddress, 1); + addr->inet = inet_parse(str, errp); + if (addr->inet == NULL) { + goto fail; +-- +1.7.1 + diff --git a/SOURCES/kvm-qemu-socket-zero-initialize-SocketAddress.patch b/SOURCES/kvm-qemu-socket-zero-initialize-SocketAddress.patch new file mode 100644 index 0000000..4872b62 --- /dev/null +++ b/SOURCES/kvm-qemu-socket-zero-initialize-SocketAddress.patch @@ -0,0 +1,46 @@ +From aa57fbfca8a627f38b2d22585c8d410b7d512231 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 14 Oct 2013 13:35:09 +0200 +Subject: [PATCH 02/18] qemu-socket: zero-initialize SocketAddress + +RH-Author: Gerd Hoffmann +Message-id: <1381757723-23134-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54863 +O-Subject: [RHEL-7 qemu-kvm PATCH 01/15] qemu-socket: zero-initialize SocketAddress +Bugzilla: 922010 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Signed-off-by: Michael Tokarev +(cherry picked from commit afde3f8b9923892d21a735993f533e5d8b60e0b0) +--- + util/qemu-sockets.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + util/qemu-sockets.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index 96eca2a..86fb09c 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -848,9 +848,9 @@ int unix_nonblocking_connect(const char *path, + + SocketAddress *socket_parse(const char *str, Error **errp) + { +- SocketAddress *addr = NULL; ++ SocketAddress *addr; + +- addr = g_new(SocketAddress, 1); ++ addr = g_new0(SocketAddress, 1); + if (strstart(str, "unix:", NULL)) { + if (str[5] == '\0') { + error_setg(errp, "invalid Unix socket address"); +-- +1.7.1 + diff --git a/SOURCES/kvm-qerror-drop-QERR_OPEN_FILE_FAILED-macro.patch b/SOURCES/kvm-qerror-drop-QERR_OPEN_FILE_FAILED-macro.patch new file mode 100644 index 0000000..6488dec --- /dev/null +++ b/SOURCES/kvm-qerror-drop-QERR_OPEN_FILE_FAILED-macro.patch @@ -0,0 +1,48 @@ +From 079e736f93a50e24b6a9d5fc3d11e25175ce8aea Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:31 +0100 +Subject: [PATCH 12/29] qerror: drop QERR_OPEN_FILE_FAILED macro + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-9-git-send-email-lersek@redhat.com> +Patchwork-id: 55198 +O-Subject: [RHEL-7 qemu-kvm PATCH 8/8] qerror: drop QERR_OPEN_FILE_FAILED macro +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Not used since the last commit. + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit dbfbc6373441e436ac6e2bcf7a8acb284225aa21) +Signed-off-by: Laszlo Ersek +--- + include/qapi/qmp/qerror.h | 3 --- + 1 file changed, 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/qapi/qmp/qerror.h | 3 --- + 1 files changed, 0 insertions(+), 3 deletions(-) + +diff --git a/include/qapi/qmp/qerror.h b/include/qapi/qmp/qerror.h +index 6c0a18d..c30c2f6 100644 +--- a/include/qapi/qmp/qerror.h ++++ b/include/qapi/qmp/qerror.h +@@ -177,9 +177,6 @@ void assert_no_error(Error *err); + #define QERR_NOT_SUPPORTED \ + ERROR_CLASS_GENERIC_ERROR, "Not supported" + +-#define QERR_OPEN_FILE_FAILED \ +- ERROR_CLASS_GENERIC_ERROR, "Could not open '%s'" +- + #define QERR_PERMISSION_DENIED \ + ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation" + +-- +1.7.1 + diff --git a/SOURCES/kvm-qga-create-state-directory-on-win32.patch b/SOURCES/kvm-qga-create-state-directory-on-win32.patch new file mode 100644 index 0000000..4d0925a --- /dev/null +++ b/SOURCES/kvm-qga-create-state-directory-on-win32.patch @@ -0,0 +1,57 @@ +From 7f69c4a541318610bef76295163cf4d7907d2339 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:25 +0200 +Subject: [PATCH 04/28] qga: create state directory on win32 + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-5-git-send-email-lersek@redhat.com> +Patchwork-id: 52867 +O-Subject: [RHEL-7 qemu-kvm PATCH 4/6] qga: create state directory on win32 +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +On Win32 the local state directory is application specific and users might +expect qemu-ga to create it automatically. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael Roth +(cherry picked from commit bf12c1fa8c78e3c667f2fe2ecc656f4f3cfb914e) +--- + qga/main.c | 14 ++++++++++++++ + 1 files changed, 14 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qga/main.c | 14 ++++++++++++++ + 1 files changed, 14 insertions(+), 0 deletions(-) + +diff --git a/qga/main.c b/qga/main.c +index 050b968..e49a6dd 100644 +--- a/qga/main.c ++++ b/qga/main.c +@@ -1042,6 +1042,20 @@ int main(int argc, char **argv) + } + } + ++#ifdef _WIN32 ++ /* On win32 the state directory is application specific (be it the default ++ * or a user override). We got past the command line parsing; let's create ++ * the directory (with any intermediate directories). If we run into an ++ * error later on, we won't try to clean up the directory, it is considered ++ * persistent. ++ */ ++ if (g_mkdir_with_parents(state_dir, S_IRWXU) == -1) { ++ g_critical("unable to create (an ancestor of) the state directory" ++ " '%s': %s", state_dir, strerror(errno)); ++ return EXIT_FAILURE; ++ } ++#endif ++ + s = g_malloc0(sizeof(GAState)); + s->log_level = log_level; + s->log_file = stderr; +-- +1.7.1 + diff --git a/SOURCES/kvm-qga-determine-default-state-dir-and-pidfile-dynamica.patch b/SOURCES/kvm-qga-determine-default-state-dir-and-pidfile-dynamica.patch new file mode 100644 index 0000000..b7371b6 --- /dev/null +++ b/SOURCES/kvm-qga-determine-default-state-dir-and-pidfile-dynamica.patch @@ -0,0 +1,124 @@ +From 211077f1cceb5f814d0750b183ff19995b37c6d3 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:23 +0200 +Subject: [PATCH 02/28] qga: determine default state dir and pidfile dynamically + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-3-git-send-email-lersek@redhat.com> +Patchwork-id: 52861 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/6] qga: determine default state dir and pidfile dynamically +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +No effective change on POSIX, but on Win32 the defaults come from the +environment / session. + +Since commit 39097daf ("qemu-ga: use key-value store to avoid recycling fd +handles after restart") we've relied on the state directory for the fd +handles' key-value store. Even though we don't support the guest-file-* +commands on win32 yet, the key-value store is written, and it's the first +use of the state directory on win32. We should have a sensible default for +its location. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Michael Roth +(cherry picked from commit c394ecb7bf55b7234f852b9c8518aefb5d0943fa) +--- + qga/main.c | 32 ++++++++++++++++++++++++++------ + 1 files changed, 26 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qga/main.c | 32 ++++++++++++++++++++++++++------ + 1 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/qga/main.c b/qga/main.c +index c2ba5d9..050b968 100644 +--- a/qga/main.c ++++ b/qga/main.c +@@ -45,16 +45,21 @@ + + #ifndef _WIN32 + #define QGA_VIRTIO_PATH_DEFAULT "/dev/virtio-ports/org.qemu.guest_agent.0" ++#define QGA_STATE_RELATIVE_DIR "run" + #else + #define QGA_VIRTIO_PATH_DEFAULT "\\\\.\\Global\\org.qemu.guest_agent.0" ++#define QGA_STATE_RELATIVE_DIR "qemu-ga" + #endif +-#define QGA_STATEDIR_DEFAULT CONFIG_QEMU_LOCALSTATEDIR "/run" +-#define QGA_PIDFILE_DEFAULT QGA_STATEDIR_DEFAULT "/qemu-ga.pid" + #ifdef CONFIG_FSFREEZE + #define QGA_FSFREEZE_HOOK_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze-hook" + #endif + #define QGA_SENTINEL_BYTE 0xFF + ++static struct { ++ const char *state_dir; ++ const char *pidfile; ++} dfl_pathnames; ++ + typedef struct GAPersistentState { + #define QGA_PSTATE_DEFAULT_FD_COUNTER 1000 + int64_t fd_counter; +@@ -106,6 +111,17 @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data, + VOID WINAPI service_main(DWORD argc, TCHAR *argv[]); + #endif + ++static void ++init_dfl_pathnames(void) ++{ ++ g_assert(dfl_pathnames.state_dir == NULL); ++ g_assert(dfl_pathnames.pidfile == NULL); ++ dfl_pathnames.state_dir = qemu_get_local_state_pathname( ++ QGA_STATE_RELATIVE_DIR); ++ dfl_pathnames.pidfile = qemu_get_local_state_pathname( ++ QGA_STATE_RELATIVE_DIR G_DIR_SEPARATOR_S "qemu-ga.pid"); ++} ++ + static void quit_handler(int sig) + { + /* if we're frozen, don't exit unless we're absolutely forced to, +@@ -198,11 +214,11 @@ static void usage(const char *cmd) + " -h, --help display this help and exit\n" + "\n" + "Report bugs to \n" +- , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, QGA_PIDFILE_DEFAULT, ++ , cmd, QEMU_VERSION, QGA_VIRTIO_PATH_DEFAULT, dfl_pathnames.pidfile, + #ifdef CONFIG_FSFREEZE + QGA_FSFREEZE_HOOK_DEFAULT, + #endif +- QGA_STATEDIR_DEFAULT); ++ dfl_pathnames.state_dir); + } + + static const char *ga_log_level_str(GLogLevelFlags level) +@@ -908,11 +924,11 @@ int main(int argc, char **argv) + const char *sopt = "hVvdm:p:l:f:F::b:s:t:"; + const char *method = NULL, *path = NULL; + const char *log_filepath = NULL; +- const char *pid_filepath = QGA_PIDFILE_DEFAULT; ++ const char *pid_filepath; + #ifdef CONFIG_FSFREEZE + const char *fsfreeze_hook = NULL; + #endif +- const char *state_dir = QGA_STATEDIR_DEFAULT; ++ const char *state_dir; + #ifdef _WIN32 + const char *service = NULL; + #endif +@@ -942,6 +958,10 @@ int main(int argc, char **argv) + + module_call_init(MODULE_INIT_QAPI); + ++ init_dfl_pathnames(); ++ pid_filepath = dfl_pathnames.pidfile; ++ state_dir = dfl_pathnames.state_dir; ++ + while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { + switch (ch) { + case 'm': +-- +1.7.1 + diff --git a/SOURCES/kvm-qga-move-logfiles-to-new-directory-for-easier-SELinu.patch b/SOURCES/kvm-qga-move-logfiles-to-new-directory-for-easier-SELinu.patch new file mode 100644 index 0000000..20799ad --- /dev/null +++ b/SOURCES/kvm-qga-move-logfiles-to-new-directory-for-easier-SELinu.patch @@ -0,0 +1,58 @@ +From db7dfa77ec3dc8908f3adb94eea121325e8ecda6 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 18 Sep 2013 16:05:42 +0200 +Subject: [PATCH 27/29] qga: move logfiles to new directory for easier SELinux labeling (RHEL only) + +RH-Author: Laszlo Ersek +Message-id: <1379520342-23063-1-git-send-email-lersek@redhat.com> +Patchwork-id: 54449 +O-Subject: [RHEL-7 qemu-kvm PATCH] qga: move logfiles to new directory for easier SELinux labeling (RHEL only) +Bugzilla: 1009491 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Paolo Bonzini + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1009491 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6300016 + +Tested by me (with manual labeling for now). + +While discussing RHEL-6 selinux-policy bug 964345 ("SELinux policy +prevents qemu guest agent from running main fsfreeze hook script, and from +creating random files"), SELinux developers suggested that the normal qga +logfile, and the fsfreeze hook logfile (which is new in RHEL-6.5) be moved +to a dedicated directory for easier SELinux labeling. + +In RHEL-7 (selinux-policy bug: 1005890) only the fsfreeze hook log exists +as a separate file; the normal qga log is part of the system journal. + +RHEL-7 only patch. + +Signed-off-by: Laszlo Ersek +--- + redhat/qemu-kvm.spec.template | 4 ++++ + scripts/qemu-guest-agent/fsfreeze-hook | 2 +- + 2 files changed, 5 insertions(+), 1 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + redhat/qemu-kvm.spec.template | 4 ++++ + scripts/qemu-guest-agent/fsfreeze-hook | 2 +- + 2 files changed, 5 insertions(+), 1 deletions(-) + +diff --git a/scripts/qemu-guest-agent/fsfreeze-hook b/scripts/qemu-guest-agent/fsfreeze-hook +index 45514fa..dba51c4 100755 +--- a/scripts/qemu-guest-agent/fsfreeze-hook ++++ b/scripts/qemu-guest-agent/fsfreeze-hook +@@ -7,7 +7,7 @@ + # "freeze" argument before the filesystem is frozen. And for fsfreeze-thaw + # request, it is issued with "thaw" argument after filesystem is thawed. + +-LOGFILE=/var/log/qemu-ga.fsfreeze-hook.log ++LOGFILE=/var/log/qemu-ga/fsfreeze-hook.log + + # Check whether file $1 is a backup or rpm-generated file and should be ignored + is_ignored_file() { +-- +1.7.1 + diff --git a/SOURCES/kvm-qga-save-state-directory-in-ga_install_service-RHEL-.patch b/SOURCES/kvm-qga-save-state-directory-in-ga_install_service-RHEL-.patch new file mode 100644 index 0000000..392c4c3 --- /dev/null +++ b/SOURCES/kvm-qga-save-state-directory-in-ga_install_service-RHEL-.patch @@ -0,0 +1,61 @@ +From e134588808798e0e2059bfc2bfcecea0f3287abf Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 31 Jul 2013 14:03:26 +0200 +Subject: [PATCH 05/28] qga: save state directory in ga_install_service() -- RHEL-7 fixup + +RH-Author: Laszlo Ersek +Message-id: <1375279407-13573-6-git-send-email-lersek@redhat.com> +Patchwork-id: 52866 +O-Subject: [RHEL-7 qemu-kvm PATCH 5/6] qga: save state directory in ga_install_service() -- RHEL-7 fixup +Bugzilla: 964304 +RH-Acked-by: Michal Novotny +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Paolo Bonzini + +If the user selects a non-default state directory at service installation +time, we should remember it in the registered service. + +In RHEL-7 we're getting the fix for CVE-2013-2231 and upstream commit + + a839ee77 qga: save state directory in ga_install_service() + +in reverse order. + +Qemu-1.6 saw "a839ee77" first, and the CVE fix second. For qemu-1.5.2, +Mike Roth pulled in part of "a839ee77" as "31c6ed20", and then applied the +CVE fix. This patch adds the rest of "a839ee77". + +Signed-off-by: Laszlo Ersek +--- + qga/main.c | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + qga/main.c | 10 +++++++++- + 1 files changed, 9 insertions(+), 1 deletions(-) + +diff --git a/qga/main.c b/qga/main.c +index e49a6dd..0e04e73 100644 +--- a/qga/main.c ++++ b/qga/main.c +@@ -1023,7 +1023,15 @@ int main(int argc, char **argv) + service = optarg; + if (strcmp(service, "install") == 0) { + const char *fixed_state_dir; +- return ga_install_service(path, log_filepath, state_dir); ++ ++ /* If the user passed the "-t" option, we save that state dir ++ * in the service. Otherwise we let the service fetch the state ++ * dir from the environment when it starts. ++ */ ++ fixed_state_dir = (state_dir == dfl_pathnames.state_dir) ? ++ NULL : ++ state_dir; ++ return ga_install_service(path, log_filepath, fixed_state_dir); + } else if (strcmp(service, "uninstall") == 0) { + return ga_uninstall_service(); + } else { +-- +1.7.1 + diff --git a/SOURCES/kvm-qmp-Documentation-for-BLOCK_IMAGE_CORRUPTED.patch b/SOURCES/kvm-qmp-Documentation-for-BLOCK_IMAGE_CORRUPTED.patch new file mode 100644 index 0000000..d1f6342 --- /dev/null +++ b/SOURCES/kvm-qmp-Documentation-for-BLOCK_IMAGE_CORRUPTED.patch @@ -0,0 +1,72 @@ +From c37b7417ab2bdc1c6880e192c5d80f865f7ed089 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:22 +0100 +Subject: [PATCH 29/87] qmp: Documentation for BLOCK_IMAGE_CORRUPTED + +RH-Author: Max Reitz +Message-id: <1383604354-12743-32-git-send-email-mreitz@redhat.com> +Patchwork-id: 55331 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 31/43] qmp: Documentation for BLOCK_IMAGE_CORRUPTED +Bugzilla: 1004347 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +BZ: 1004347 + +Add an appropriate entry describing this event and its parameters into +qmp-events.txt. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 0ca0b0d5f8a87dbc6daa5095771d036d0e6dc5b4) + +Signed-off-by: Max Reitz +--- + QMP/qmp-events.txt | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + QMP/qmp-events.txt | 22 ++++++++++++++++++++++ + 1 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/QMP/qmp-events.txt b/QMP/qmp-events.txt +index 92fe5fb..e185030 100644 +--- a/QMP/qmp-events.txt ++++ b/QMP/qmp-events.txt +@@ -18,6 +18,28 @@ Example: + "data": { "actual": 944766976 }, + "timestamp": { "seconds": 1267020223, "microseconds": 435656 } } + ++BLOCK_IMAGE_CORRUPTED ++--------------------- ++ ++Emitted when a disk image is being marked corrupt. ++ ++Data: ++ ++- "device": Device name (json-string) ++- "msg": Informative message (e.g., reason for the corruption) (json-string) ++- "offset": If the corruption resulted from an image access, this is the access ++ offset into the image (json-int) ++- "size": If the corruption resulted from an image access, this is the access ++ size (json-int) ++ ++Example: ++ ++{ "event": "BLOCK_IMAGE_CORRUPTED", ++ "data": { "device": "ide0-hd0", ++ "msg": "Prevented active L1 table overwrite", "offset": 196608, ++ "size": 65536 }, ++ "timestamp": { "seconds": 1378126126, "microseconds": 966463 } } ++ + BLOCK_IO_ERROR + -------------- + +-- +1.7.1 + diff --git a/SOURCES/kvm-qmp-add-ImageInfo-in-BlockDeviceInfo-used-by-query-b.patch b/SOURCES/kvm-qmp-add-ImageInfo-in-BlockDeviceInfo-used-by-query-b.patch new file mode 100644 index 0000000..06dcd32 --- /dev/null +++ b/SOURCES/kvm-qmp-add-ImageInfo-in-BlockDeviceInfo-used-by-query-b.patch @@ -0,0 +1,291 @@ +From 5c10b431d0dd4538d33c21d7a46f7c8754f42a83 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:29 +0100 +Subject: [PATCH 72/87] qmp: add ImageInfo in BlockDeviceInfo used by query-block + +RH-Author: Max Reitz +Message-id: <1383756824-6921-7-git-send-email-mreitz@redhat.com> +Patchwork-id: 55561 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 06/21] qmp: add ImageInfo in BlockDeviceInfo used by query-block +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Wenchao Xia + +BZ: 980771 + +Now image info will be retrieved as an embbed json object inside +BlockDeviceInfo, backing chain info and all related internal snapshot +info can be got in the enhanced recursive structure of ImageInfo. New +recursive member *backing-image is added to reflect the backing chain +status. + +Signed-off-by: Wenchao Xia +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 553a7e871822d933beaefbd596f0e4eed1614373) + +Signed-off-by: Max Reitz +--- + block/qapi.c | 50 ++++++++++++++++++++++++++++++++++--- + include/block/qapi.h | 4 ++- + qapi-schema.json | 10 ++++++-- + qmp-commands.hx | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++-- + 4 files changed, 125 insertions(+), 8 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/qapi.c | 50 ++++++++++++++++++++++++++++++++++-- + include/block/qapi.h | 4 ++- + qapi-schema.json | 10 ++++++- + qmp-commands.hx | 69 ++++++++++++++++++++++++++++++++++++++++++++++++- + 4 files changed, 125 insertions(+), 8 deletions(-) + +diff --git a/block/qapi.c b/block/qapi.c +index e9d8b74..a4bc411 100644 +--- a/block/qapi.c ++++ b/block/qapi.c +@@ -94,6 +94,13 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, + * @p_info: location to store image information + * @errp: location to store error information + * ++ * Store "flat" image information in @p_info. ++ * ++ * "Flat" means it does *not* query backing image information, ++ * i.e. (*pinfo)->has_backing_image will be set to false and ++ * (*pinfo)->backing_image to NULL even when the image does in fact have ++ * a backing image. ++ * + * @p_info will be set only on success. On error, store error in @errp. + */ + void bdrv_query_image_info(BlockDriverState *bs, +@@ -167,9 +174,15 @@ void bdrv_query_image_info(BlockDriverState *bs, + *p_info = info; + } + +-BlockInfo *bdrv_query_info(BlockDriverState *bs) ++/* @p_info will be set only on success. */ ++void bdrv_query_info(BlockDriverState *bs, ++ BlockInfo **p_info, ++ Error **errp) + { + BlockInfo *info = g_malloc0(sizeof(*info)); ++ BlockDriverState *bs0; ++ ImageInfo **p_image_info; ++ Error *local_err = NULL; + info->device = g_strdup(bs->device_name); + info->type = g_strdup("unknown"); + info->locked = bdrv_dev_is_medium_locked(bs); +@@ -223,8 +236,30 @@ BlockInfo *bdrv_query_info(BlockDriverState *bs) + info->inserted->iops_wr = + bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE]; + } ++ ++ bs0 = bs; ++ p_image_info = &info->inserted->image; ++ while (1) { ++ bdrv_query_image_info(bs0, p_image_info, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ goto err; ++ } ++ if (bs0->drv && bs0->backing_hd) { ++ bs0 = bs0->backing_hd; ++ (*p_image_info)->has_backing_image = true; ++ p_image_info = &((*p_image_info)->backing_image); ++ } else { ++ break; ++ } ++ } + } +- return info; ++ ++ *p_info = info; ++ return; ++ ++ err: ++ qapi_free_BlockInfo(info); + } + + BlockStats *bdrv_query_stats(const BlockDriverState *bs) +@@ -261,16 +296,25 @@ BlockInfoList *qmp_query_block(Error **errp) + { + BlockInfoList *head = NULL, **p_next = &head; + BlockDriverState *bs = NULL; ++ Error *local_err = NULL; + + while ((bs = bdrv_next(bs))) { + BlockInfoList *info = g_malloc0(sizeof(*info)); +- info->value = bdrv_query_info(bs); ++ bdrv_query_info(bs, &info->value, &local_err); ++ if (error_is_set(&local_err)) { ++ error_propagate(errp, local_err); ++ goto err; ++ } + + *p_next = info; + p_next = &info->next; + } + + return head; ++ ++ err: ++ qapi_free_BlockInfoList(head); ++ return NULL; + } + + BlockStatsList *qmp_query_blockstats(Error **errp) +diff --git a/include/block/qapi.h b/include/block/qapi.h +index ab1f48f..0496cc9 100644 +--- a/include/block/qapi.h ++++ b/include/block/qapi.h +@@ -35,7 +35,9 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs, + void bdrv_query_image_info(BlockDriverState *bs, + ImageInfo **p_info, + Error **errp); +-BlockInfo *bdrv_query_info(BlockDriverState *s); ++void bdrv_query_info(BlockDriverState *bs, ++ BlockInfo **p_info, ++ Error **errp); + BlockStats *bdrv_query_stats(const BlockDriverState *bs); + + void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f, +diff --git a/qapi-schema.json b/qapi-schema.json +index 32b41b0..4091b99 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -236,6 +236,8 @@ + # + # @snapshots: #optional list of VM snapshots + # ++# @backing-image: #optional info of the backing image (since 1.6) ++# + # Since: 1.3 + # + ## +@@ -245,7 +247,8 @@ + '*actual-size': 'int', 'virtual-size': 'int', + '*cluster-size': 'int', '*encrypted': 'bool', + '*backing-filename': 'str', '*full-backing-filename': 'str', +- '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'] } } ++ '*backing-filename-format': 'str', '*snapshots': ['SnapshotInfo'], ++ '*backing-image': 'ImageInfo' } } + + ## + # @ImageCheck: +@@ -768,6 +771,8 @@ + # + # @iops_wr: write I/O operations per second is specified + # ++# @image: the info of image used (since: 1.6) ++# + # Since: 0.14.0 + # + # Notes: This interface is only found in @BlockInfo. +@@ -777,7 +782,8 @@ + '*backing_file': 'str', 'backing_file_depth': 'int', + 'encrypted': 'bool', 'encryption_key_missing': 'bool', + 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int', +- 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} } ++ 'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int', ++ 'image': 'ImageInfo' } } + + ## + # @BlockDeviceIoStatus: +diff --git a/qmp-commands.hx b/qmp-commands.hx +index d1f6f8b..f71c34e 100644 +--- a/qmp-commands.hx ++++ b/qmp-commands.hx +@@ -1713,6 +1713,47 @@ Each json-object contain the following: + - "iops": limit total I/O operations per second (json-int) + - "iops_rd": limit read operations per second (json-int) + - "iops_wr": limit write operations per second (json-int) ++ - "image": the detail of the image, it is a json-object containing ++ the following: ++ - "filename": image file name (json-string) ++ - "format": image format (json-string) ++ - "virtual-size": image capacity in bytes (json-int) ++ - "dirty-flag": true if image is not cleanly closed, not present ++ means clean (json-bool, optional) ++ - "actual-size": actual size on disk in bytes of the image, not ++ present when image does not support thin ++ provision (json-int, optional) ++ - "cluster-size": size of a cluster in bytes, not present if image ++ format does not support it (json-int, optional) ++ - "encrypted": true if the image is encrypted, not present means ++ false or the image format does not support ++ encryption (json-bool, optional) ++ - "backing_file": backing file name, not present means no backing ++ file is used or the image format does not ++ support backing file chain ++ (json-string, optional) ++ - "full-backing-filename": full path of the backing file, not ++ present if it equals backing_file or no ++ backing file is used ++ (json-string, optional) ++ - "backing-filename-format": the format of the backing file, not ++ present means unknown or no backing ++ file (json-string, optional) ++ - "snapshots": the internal snapshot info, it is an optional list ++ of json-object containing the following: ++ - "id": unique snapshot id (json-string) ++ - "name": snapshot name (json-string) ++ - "vm-state-size": size of the VM state in bytes (json-int) ++ - "date-sec": UTC date of the snapshot in seconds (json-int) ++ - "date-nsec": fractional part in nanoseconds to be used with ++ date-sec(json-int) ++ - "vm-clock-sec": VM clock relative to boot in seconds ++ (json-int) ++ - "vm-clock-nsec": fractional part in nanoseconds to be used ++ with vm-clock-sec (json-int) ++ - "backing-image": the detail of the backing image, it is an ++ optional json-object only present when a ++ backing image present for this image + + - "io-status": I/O operation status, only present if the device supports it + and the VM is configured to stop on errors. It's always reset +@@ -1733,14 +1774,38 @@ Example: + "ro":false, + "drv":"qcow2", + "encrypted":false, +- "file":"disks/test.img", +- "backing_file_depth":0, ++ "file":"disks/test.qcow2", ++ "backing_file_depth":1, + "bps":1000000, + "bps_rd":0, + "bps_wr":0, + "iops":1000000, + "iops_rd":0, + "iops_wr":0, ++ "image":{ ++ "filename":"disks/test.qcow2", ++ "format":"qcow2", ++ "virtual-size":2048000, ++ "backing_file":"base.qcow2", ++ "full-backing-filename":"disks/base.qcow2", ++ "backing-filename-format:"qcow2", ++ "snapshots":[ ++ { ++ "id": "1", ++ "name": "snapshot1", ++ "vm-state-size": 0, ++ "date-sec": 10000200, ++ "date-nsec": 12, ++ "vm-clock-sec": 206, ++ "vm-clock-nsec": 30 ++ } ++ ], ++ "backing-image":{ ++ "filename":"disks/base.qcow2", ++ "format":"qcow2", ++ "virtual-size":2048000 ++ } ++ } + }, + "type":"unknown" + }, +-- +1.7.1 + diff --git a/SOURCES/kvm-qtest-Don-t-reset-on-qtest-chardev-connect.patch b/SOURCES/kvm-qtest-Don-t-reset-on-qtest-chardev-connect.patch new file mode 100644 index 0000000..ab8b8d2 --- /dev/null +++ b/SOURCES/kvm-qtest-Don-t-reset-on-qtest-chardev-connect.patch @@ -0,0 +1,59 @@ +From a90030205cdd1c640537ddd5353a900291243746 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:19 +0200 +Subject: [PATCH 09/14] qtest: Don't reset on qtest chardev connect + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-10-git-send-email-armbru@redhat.com> +Patchwork-id: 54565 +O-Subject: [PATCH 7.0 qemu-kvm 09/10] qtest: Don't reset on qtest chardev connect +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +libqtest's qtest_init() connecting to the qtest socket triggers reset. +This was coded in the hope we could use the same QEMU process for +multiple tests that way. Never used. Injects an extra reset even +when it's not used, and that can mess up tests such as the one of +-boot once I'm about to add. Drop it. + +Signed-off-by: Markus Armbruster +Message-id: 1372254743-15808-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit ba646ff6a3149f416424122c628e798be4957997) +--- + qtest.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +Signed-off-by: Michal Novotny +--- + qtest.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/qtest.c b/qtest.c +index 07a9612..74f1842 100644 +--- a/qtest.c ++++ b/qtest.c +@@ -472,7 +472,12 @@ static void qtest_event(void *opaque, int event) + + switch (event) { + case CHR_EVENT_OPENED: +- qemu_system_reset(false); ++ /* ++ * We used to call qemu_system_reset() here, hoping we could ++ * use the same process for multiple tests that way. Never ++ * used. Injects an extra reset even when it's not used, and ++ * that can mess up tests, e.g. -boot once. ++ */ + for (i = 0; i < ARRAY_SIZE(irq_levels); i++) { + irq_levels[i] = 0; + } +-- +1.7.11.7 + diff --git a/SOURCES/kvm-qxl-fix-local-renderer.patch b/SOURCES/kvm-qxl-fix-local-renderer.patch new file mode 100644 index 0000000..e70c783 --- /dev/null +++ b/SOURCES/kvm-qxl-fix-local-renderer.patch @@ -0,0 +1,82 @@ +From 4a19f6aff24c38ede727026ee6695e561aef1366 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 12 Sep 2013 09:12:56 +0200 +Subject: [PATCH 01/11] qxl: fix local renderer + +RH-Author: Gerd Hoffmann +Message-id: <1378977176-19133-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54333 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] qxl: fix local renderer +Bugzilla: 1005036 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Markus Armbruster +RH-Acked-by: Hans de Goede + +The local spice renderer assumes the primary surface is located at the +start of the "ram" bar. This used to be a requirement in qxl hardware +revision 1. In revision 2+ this is relaxed. Nevertheless guest drivers +continued to use the traditional location, for historical and backward +compatibility reasons. The qxl kms driver doesn't though as it depends +on qxl revision 4+ anyway. + +Result is that local rendering is hosed for recent linux guests, you'll +get pixel garbage with non-spice ui (gtk, sdl, vnc) and when doing +screendumps. Fix that by doing a proper mapping of the guest-specified +memory location. + +https://bugzilla.redhat.com/show_bug.cgi?id=948717 + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit c58c7b959b93b864a27fd6b3646ee1465ab8832b) +--- + hw/display/qxl-render.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/display/qxl-render.c | 15 ++++++++++----- + 1 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c +index f511a62..f654476 100644 +--- a/hw/display/qxl-render.c ++++ b/hw/display/qxl-render.c +@@ -31,10 +31,6 @@ static void qxl_blit(PCIQXLDevice *qxl, QXLRect *rect) + if (is_buffer_shared(surface)) { + return; + } +- if (!qxl->guest_primary.data) { +- trace_qxl_render_blit_guest_primary_initialized(); +- qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); +- } + trace_qxl_render_blit(qxl->guest_primary.qxl_stride, + rect->left, rect->right, rect->top, rect->bottom); + src = qxl->guest_primary.data; +@@ -104,7 +100,12 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) + + if (qxl->guest_primary.resized) { + qxl->guest_primary.resized = 0; +- qxl->guest_primary.data = memory_region_get_ram_ptr(&qxl->vga.vram); ++ qxl->guest_primary.data = qxl_phys2virt(qxl, ++ qxl->guest_primary.surface.mem, ++ MEMSLOT_GROUP_GUEST); ++ if (!qxl->guest_primary.data) { ++ return; ++ } + qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); + qxl->num_dirty_rects = 1; + trace_qxl_render_guest_primary_resized( +@@ -128,6 +129,10 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) + } + dpy_gfx_replace_surface(vga->con, surface); + } ++ ++ if (!qxl->guest_primary.data) { ++ return; ++ } + for (i = 0; i < qxl->num_dirty_rects; i++) { + if (qemu_spice_rect_is_empty(qxl->dirty+i)) { + break; +-- +1.7.1 + diff --git a/SOURCES/kvm-raw-posix-report-unwritten-extents-as-zero.patch b/SOURCES/kvm-raw-posix-report-unwritten-extents-as-zero.patch new file mode 100644 index 0000000..226e318 --- /dev/null +++ b/SOURCES/kvm-raw-posix-report-unwritten-extents-as-zero.patch @@ -0,0 +1,45 @@ +From e58d84de9cb73fba1b98c57edc63e751b4171c4e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:45 +0200 +Subject: [PATCH 20/81] raw-posix: report unwritten extents as zero + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-21-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55003 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 20/26] raw-posix: report unwritten extents as zero +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +These are created for example with XFS_IOC_ZERO_RANGE. + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit f5f7abcfd50bca38ae278a9c7a3ed60fba3d76dc) +--- + block/raw-posix.c | 3 +++ + 1 file changed, 3 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-posix.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/block/raw-posix.c b/block/raw-posix.c +index a829ce0..c7ab908 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -1128,6 +1128,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + } else { + data = f.fe.fe_logical; + hole = f.fe.fe_logical + f.fe.fe_length; ++ if (f.fe.fe_flags & FIEMAP_EXTENT_UNWRITTEN) { ++ ret |= BDRV_BLOCK_ZERO; ++ } + } + + #elif defined SEEK_HOLE && defined SEEK_DATA +-- +1.7.1 + diff --git a/SOURCES/kvm-raw-posix-return-get_block_status-data-and-flags.patch b/SOURCES/kvm-raw-posix-return-get_block_status-data-and-flags.patch new file mode 100644 index 0000000..1a411f1 --- /dev/null +++ b/SOURCES/kvm-raw-posix-return-get_block_status-data-and-flags.patch @@ -0,0 +1,94 @@ +From 145376957366516a0b47f4a83d93b6c0c026e469 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 18 Oct 2013 08:14:44 +0200 +Subject: [PATCH 19/81] raw-posix: return get_block_status data and flags + +RH-Author: Paolo Bonzini +Message-id: <1382084091-16636-20-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55002 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 19/26] raw-posix: return get_block_status data and flags +Bugzilla: 989646 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +Reviewed-by: Eric Blake +Signed-off-by: Paolo Bonzini +(cherry picked from commit 63390a8d14c9006f42bdaab22291c9c97676322d) +--- + block/raw-posix.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-posix.c | 17 ++++++++++------- + 1 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/block/raw-posix.c b/block/raw-posix.c +index 9a7c5a8..a829ce0 100644 +--- a/block/raw-posix.c ++++ b/block/raw-posix.c +@@ -1089,7 +1089,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + int nb_sectors, int *pnum) + { + off_t start, data, hole; +- int ret; ++ int64_t ret; + + ret = fd_open(bs); + if (ret < 0) { +@@ -1097,6 +1097,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + } + + start = sector_num * BDRV_SECTOR_SIZE; ++ ret = BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID | start; + + #ifdef CONFIG_FIEMAP + +@@ -1114,7 +1115,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) { + /* Assume everything is allocated. */ + *pnum = nb_sectors; +- return 1; ++ return ret; + } + + if (f.fm.fm_mapped_extents == 0) { +@@ -1141,7 +1142,7 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + + /* Most likely EINVAL. Assume everything is allocated. */ + *pnum = nb_sectors; +- return 1; ++ return ret; + } + + if (hole > start) { +@@ -1154,19 +1155,21 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs, + } + } + #else +- *pnum = nb_sectors; +- return 1; ++ data = 0; ++ hole = start + nb_sectors * BDRV_SECTOR_SIZE; + #endif + + if (data <= start) { + /* On a data extent, compute sectors to the end of the extent. */ + *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE); +- return 1; + } else { + /* On a hole, compute sectors to the beginning of the next extent. */ + *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE); +- return 0; ++ ret &= ~BDRV_BLOCK_DATA; ++ ret |= BDRV_BLOCK_ZERO; + } ++ ++ return ret; + } + + static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs, +-- +1.7.1 + diff --git a/SOURCES/kvm-rbd-Only-look-for-qemu-specific-copy-of-librbd.so.1.patch b/SOURCES/kvm-rbd-Only-look-for-qemu-specific-copy-of-librbd.so.1.patch new file mode 100644 index 0000000..6e564a5 --- /dev/null +++ b/SOURCES/kvm-rbd-Only-look-for-qemu-specific-copy-of-librbd.so.1.patch @@ -0,0 +1,53 @@ +From ece4ff225717364edc3136599113709dacdc5731 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Kevin Wolf +Date: Thu, 31 Oct 2013 12:13:14 +0100 +Subject: [PATCH 13/14] rbd: Only look for qemu-specific copy of librbd.so.1 + +RH-Author: Kevin Wolf +Message-id: <1383221595-24285-3-git-send-email-kwolf@redhat.com> +Patchwork-id: 55184 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 2/3] rbd: Only look for qemu-specific copy of librbd.so.1 +Bugzilla: 989608 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +Bugzilla: 989608 +Upstream status: n/a +Downstream status: Forward ported from RHEL 6 + +For non-technical reasons, we don't want to pick up a random librbd that +may be installed for other reasons on this system, but only a librbd +that was specificially installed in order to consciously extend qemu. + +So change the gmodule_open() argument to an absolute path. + +Signed-off-by: Kevin Wolf +--- + block/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Michal Novotny +--- + block/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/rbd.c b/block/rbd.c +index 7f5cfca..7b6e03b 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -1122,7 +1122,7 @@ static int qemu_rbd_load_libs(void) + return -1; + } + +- librbd_handle = g_module_open("librbd.so.1", 0); ++ librbd_handle = g_module_open("/usr/lib64/qemu/librbd.so.1", 0); + if (!librbd_handle) { + error_report("error loading librbd: %s", g_module_error()); + return -1; +-- +1.7.11.7 + diff --git a/SOURCES/kvm-rbd-link-and-load-librbd-dynamically.patch b/SOURCES/kvm-rbd-link-and-load-librbd-dynamically.patch new file mode 100644 index 0000000..4f74bef --- /dev/null +++ b/SOURCES/kvm-rbd-link-and-load-librbd-dynamically.patch @@ -0,0 +1,614 @@ +From 64d9964fc97fc525b86e12c5f385dea7e646a3b0 Mon Sep 17 00:00:00 2001 +Message-Id: <64d9964fc97fc525b86e12c5f385dea7e646a3b0.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Kevin Wolf +Date: Thu, 31 Oct 2013 12:13:13 +0100 +Subject: [PATCH 12/14] rbd: link and load librbd dynamically + +RH-Author: Kevin Wolf +Message-id: <1383221595-24285-2-git-send-email-kwolf@redhat.com> +Patchwork-id: 55183 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 1/3] rbd: link and load librbd dynamically +Bugzilla: 989608 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +Bugzilla: 989608 +Upstream status: Rejected +Downstream status: Forward ported from RHEL 6 + +This is the downstream-only part that gets us rid of the build-time +dependency on librbd and loads it dynamically when using an image. +It is based on a patch submitted to qemu-devel and archived as +http://lists.gnu.org/archive/html/qemu-devel/2013-04/msg01814.html + +For the forward-port to RHEL 7, I decided to implement the review +suggestions from RHEL 6 to move the function pointers out of a separate +struct to the top level, so that callers don't have to be changed +compared to upstream. This should also reduce merge conflicts in future +forward-ports. + +Note that this is not much more than compile tested; the real testing +will be done by Inktank as soon as they can access RHEL 7. + +Original commit message follows: + +This allows the rbd block driver to detect symbols in the installed +version of librbd, and enable or disable features appropriately. This +obviates the #ifdefs regarding librbd versions. + +Loading librbd dynamically also makes the rbd block driver easier to +install and package, since it removes the dependency on librbd at +build time. + +Add structures containing the necessary function pointer signatures +and types from librbd, and fill them in the first time the rbd module +is used. Use glib's g_module interface so we don't preclude future +portability, and don't have to deal with odd dlopen behavior directly. + +Internally, librbd and some libraries it depends on use C++ templates, +which mean that they each contain a defined weak symbol for their +definition. Due to the way the linker resolves duplicate symbols, the +libraries loaded by librbd end up using the template definitions from +librbd, creating a circular dependency. This means that once librbd is +loaded, it won't be unloaded. Changing this behavior might work with a +Sun ld, but there doesn't seem to be a portable (or even working with +GNU ld) way to hide these C++ symbols correctly. Instead, never unload +librbd, and explicitly make it resident. + +Signed-off-by: Josh Durgin +Signed-off-by: Kevin Wolf +--- + block/Makefile.objs | 2 +- + block/rbd.c | 218 ++++++++++++++++++++++++++++++++++++++++------------ + block/rbd_types.h | 91 ++++++++++++++++++++++ + configure | 41 +--------- + 4 files changed, 263 insertions(+), 89 deletions(-) + create mode 100644 block/rbd_types.h + +Signed-off-by: Michal Novotny +--- + block/Makefile.objs | 2 +- + block/rbd.c | 218 ++++++++++++++++++++++++++++++++++++++++------------ + block/rbd_types.h | 91 ++++++++++++++++++++++ + configure | 41 +--------- + 4 files changed, 263 insertions(+), 89 deletions(-) + create mode 100644 block/rbd_types.h + +diff --git a/block/Makefile.objs b/block/Makefile.objs +index 5f0358a..6b8d5ec 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -12,7 +12,7 @@ ifeq ($(CONFIG_POSIX),y) + block-obj-y += nbd.o sheepdog.o + block-obj-$(CONFIG_LIBISCSI) += iscsi.o + block-obj-$(CONFIG_CURL) += curl.o +-block-obj-$(CONFIG_RBD) += rbd.o ++block-obj-y += rbd.o + block-obj-$(CONFIG_GLUSTERFS) += gluster.o + block-obj-$(CONFIG_LIBSSH2) += ssh.o + endif +diff --git a/block/rbd.c b/block/rbd.c +index 0f2608b..7f5cfca 100644 +--- a/block/rbd.c ++++ b/block/rbd.c +@@ -11,13 +11,14 @@ + * GNU GPL, version 2 or (at your option) any later version. + */ + ++#include + #include + + #include "qemu-common.h" + #include "qemu/error-report.h" + #include "block/block_int.h" + +-#include ++#include "rbd_types.h" + + /* + * When specifying the image filename use: +@@ -44,13 +45,6 @@ + * leading "\". + */ + +-/* rbd_aio_discard added in 0.1.2 */ +-#if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 2) +-#define LIBRBD_SUPPORTS_DISCARD +-#else +-#undef LIBRBD_SUPPORTS_DISCARD +-#endif +- + #define OBJ_MAX_SIZE (1UL << OBJ_DEFAULT_OBJ_ORDER) + + #define RBD_MAX_CONF_NAME_SIZE 128 +@@ -106,6 +100,10 @@ typedef struct BDRVRBDState { + RADOSCB *event_rcb; + } BDRVRBDState; + ++static bool librbd_loaded; ++static GModule *librbd_handle; ++ ++static int qemu_rbd_load_libs(void); + static void rbd_aio_bh_cb(void *opaque); + + static int qemu_rbd_next_tok(char *dst, int dst_len, +@@ -310,6 +308,10 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) + return -EINVAL; + } + ++ if (qemu_rbd_load_libs() < 0) { ++ return -EIO; ++ } ++ + /* Read out options */ + while (options && options->name) { + if (!strcmp(options->name, BLOCK_OPT_SIZE)) { +@@ -487,6 +489,10 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags) + goto failed_opts; + } + ++ if (qemu_rbd_load_libs() < 0) { ++ return -EIO; ++ } ++ + clientname = qemu_rbd_parse_clientname(conf, clientname_buf); + r = rados_create(&s->cluster, clientname); + if (r < 0) { +@@ -678,28 +684,6 @@ static void rbd_aio_bh_cb(void *opaque) + } + } + +-static int rbd_aio_discard_wrapper(rbd_image_t image, +- uint64_t off, +- uint64_t len, +- rbd_completion_t comp) +-{ +-#ifdef LIBRBD_SUPPORTS_DISCARD +- return rbd_aio_discard(image, off, len, comp); +-#else +- return -ENOTSUP; +-#endif +-} +- +-static int rbd_aio_flush_wrapper(rbd_image_t image, +- rbd_completion_t comp) +-{ +-#ifdef LIBRBD_SUPPORTS_AIO_FLUSH +- return rbd_aio_flush(image, comp); +-#else +- return -ENOTSUP; +-#endif +-} +- + static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs, + int64_t sector_num, + QEMUIOVector *qiov, +@@ -762,10 +746,10 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs, + r = rbd_aio_read(s->image, off, size, buf, c); + break; + case RBD_AIO_DISCARD: +- r = rbd_aio_discard_wrapper(s->image, off, size, c); ++ r = rbd_aio_discard(s->image, off, size, c); + break; + case RBD_AIO_FLUSH: +- r = rbd_aio_flush_wrapper(s->image, c); ++ r = rbd_aio_flush(s->image, c); + break; + default: + r = -EINVAL; +@@ -806,7 +790,6 @@ static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs, + RBD_AIO_WRITE); + } + +-#ifdef LIBRBD_SUPPORTS_AIO_FLUSH + static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs, + BlockDriverCompletionFunc *cb, + void *opaque) +@@ -814,19 +797,14 @@ static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs, + return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH); + } + +-#else +- + static int qemu_rbd_co_flush(BlockDriverState *bs) + { +-#if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 1) +- /* rbd_flush added in 0.1.1 */ + BDRVRBDState *s = bs->opaque; +- return rbd_flush(s->image); +-#else ++ if (rbd_flush) { ++ return rbd_flush(s->image); ++ } + return 0; +-#endif + } +-#endif + + static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi) + { +@@ -964,7 +942,6 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, + return snap_count; + } + +-#ifdef LIBRBD_SUPPORTS_DISCARD + static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, +@@ -974,7 +951,6 @@ static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs, + return rbd_start_aio(bs, sector_num, NULL, nb_sectors, cb, opaque, + RBD_AIO_DISCARD); + } +-#endif + + static QEMUOptionParameter qemu_rbd_create_options[] = { + { +@@ -1004,16 +980,9 @@ static BlockDriver bdrv_rbd = { + + .bdrv_aio_readv = qemu_rbd_aio_readv, + .bdrv_aio_writev = qemu_rbd_aio_writev, +- +-#ifdef LIBRBD_SUPPORTS_AIO_FLUSH + .bdrv_aio_flush = qemu_rbd_aio_flush, +-#else + .bdrv_co_flush_to_disk = qemu_rbd_co_flush, +-#endif +- +-#ifdef LIBRBD_SUPPORTS_DISCARD + .bdrv_aio_discard = qemu_rbd_aio_discard, +-#endif + + .bdrv_snapshot_create = qemu_rbd_snap_create, + .bdrv_snapshot_delete = qemu_rbd_snap_remove, +@@ -1026,4 +995,153 @@ static void bdrv_rbd_init(void) + bdrv_register(&bdrv_rbd); + } + ++typedef struct LibSymbol { ++ const char *name; ++ gpointer *addr; ++} LibSymbol; ++ ++static int qemu_rbd_set_functions(GModule *lib, const LibSymbol *funcs) ++{ ++ int i = 0; ++ while (funcs[i].name) { ++ const char *name = funcs[i].name; ++ if (!g_module_symbol(lib, name, funcs[i].addr)) { ++ error_report("%s could not be loaded from librbd or librados: %s", ++ name, g_module_error()); ++ return -1; ++ } ++ ++i; ++ } ++ return 0; ++} ++ ++/* ++ * Set function pointers for basic librados and librbd ++ * functions that have always been present in these libraries. ++ */ ++static int qemu_rbd_set_mandatory_functions(void) ++{ ++ LibSymbol symbols[] = { ++ {"rados_create", ++ (gpointer *) &rados_create}, ++ {"rados_connect", ++ (gpointer *) &rados_connect}, ++ {"rados_shutdown", ++ (gpointer *) &rados_shutdown}, ++ {"rados_conf_read_file", ++ (gpointer *) &rados_conf_read_file}, ++ {"rados_conf_set", ++ (gpointer *) &rados_conf_set}, ++ {"rados_ioctx_create", ++ (gpointer *) &rados_ioctx_create}, ++ {"rados_ioctx_destroy", ++ (gpointer *) &rados_ioctx_destroy}, ++ {"rbd_create", ++ (gpointer *) &rbd_create}, ++ {"rbd_open", ++ (gpointer *) &rbd_open}, ++ {"rbd_close", ++ (gpointer *) &rbd_close}, ++ {"rbd_resize", ++ (gpointer *) &rbd_resize}, ++ {"rbd_stat", ++ (gpointer *) &rbd_stat}, ++ {"rbd_snap_list", ++ (gpointer *) &rbd_snap_list}, ++ {"rbd_snap_list_end", ++ (gpointer *) &rbd_snap_list_end}, ++ {"rbd_snap_create", ++ (gpointer *) &rbd_snap_create}, ++ {"rbd_snap_remove", ++ (gpointer *) &rbd_snap_remove}, ++ {"rbd_snap_rollback", ++ (gpointer *) &rbd_snap_rollback}, ++ {"rbd_aio_write", ++ (gpointer *) &rbd_aio_write}, ++ {"rbd_aio_read", ++ (gpointer *) &rbd_aio_read}, ++ {"rbd_aio_create_completion", ++ (gpointer *) &rbd_aio_create_completion}, ++ {"rbd_aio_get_return_value", ++ (gpointer *) &rbd_aio_get_return_value}, ++ {"rbd_aio_release", ++ (gpointer *) &rbd_aio_release}, ++ {NULL} ++ }; ++ ++ if (qemu_rbd_set_functions(librbd_handle, symbols) < 0) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Detect whether the installed version of librbd ++ * supports newer functionality, and enable or disable ++ * it appropriately in bdrv_rbd. ++ */ ++static void qemu_rbd_set_optional_functions(void) ++{ ++ if (g_module_symbol(librbd_handle, "rbd_flush", ++ (gpointer *) &rbd_flush)) { ++ bdrv_rbd.bdrv_aio_flush = NULL; ++ bdrv_rbd.bdrv_co_flush_to_disk = qemu_rbd_co_flush; ++ } else { ++ rbd_flush = NULL; ++ bdrv_rbd.bdrv_co_flush_to_disk = NULL; ++ } ++ ++ if (g_module_symbol(librbd_handle, "rbd_aio_flush", ++ (gpointer *) &rbd_aio_flush)) { ++ bdrv_rbd.bdrv_co_flush_to_disk = NULL; ++ bdrv_rbd.bdrv_aio_flush = qemu_rbd_aio_flush; ++ } else { ++ rbd_aio_flush = NULL; ++ bdrv_rbd.bdrv_aio_flush = NULL; ++ } ++ ++ if (g_module_symbol(librbd_handle, "rbd_aio_discard", ++ (gpointer *) &rbd_aio_discard)) { ++ bdrv_rbd.bdrv_aio_discard = qemu_rbd_aio_discard; ++ } else { ++ rbd_aio_discard = NULL; ++ bdrv_rbd.bdrv_aio_discard = NULL; ++ } ++} ++ ++static int qemu_rbd_load_libs(void) ++{ ++ if (librbd_loaded) { ++ return 0; ++ } ++ ++ if (!g_module_supported()) { ++ error_report("modules are not supported on this platform: %s", ++ g_module_error()); ++ return -1; ++ } ++ ++ librbd_handle = g_module_open("librbd.so.1", 0); ++ if (!librbd_handle) { ++ error_report("error loading librbd: %s", g_module_error()); ++ return -1; ++ } ++ ++ /* ++ * Due to c++ templates used in librbd/librados and their ++ * dependencies, and linker duplicate trimming rules, closing ++ * librbd would leave it mapped. Make this explicit. ++ */ ++ g_module_make_resident(librbd_handle); ++ ++ if (qemu_rbd_set_mandatory_functions() < 0) { ++ return -1; ++ } ++ qemu_rbd_set_optional_functions(); ++ librbd_loaded = true; ++ ++ return 0; ++} ++ + block_init(bdrv_rbd_init); +diff --git a/block/rbd_types.h b/block/rbd_types.h +new file mode 100644 +index 0000000..f327cb4 +--- /dev/null ++++ b/block/rbd_types.h +@@ -0,0 +1,91 @@ ++/* ++ * Types and signatures for librados and librbd ++ * ++ * Copyright (C) 2013 Inktank Storage Inc. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#ifndef QEMU_BLOCK_RBD_TYPES_H ++#define QEMU_BLOCK_RBD_TYPES_H ++ ++/* types from librados used by the rbd block driver */ ++ ++typedef void *rados_t; ++typedef void *rados_ioctx_t; ++ ++static int (*rados_create)(rados_t *cluster, const char * const id); ++static int (*rados_connect)(rados_t cluster); ++static void (*rados_shutdown)(rados_t cluster); ++static int (*rados_conf_read_file)(rados_t cluster, const char *path); ++static int (*rados_conf_set)(rados_t cluster, const char *option, ++ const char *value); ++static int (*rados_ioctx_create)(rados_t cluster, const char *pool_name, ++ rados_ioctx_t *ioctx); ++static void (*rados_ioctx_destroy)(rados_ioctx_t io); ++ ++/* types from librbd used by the rbd block driver*/ ++ ++typedef void *rbd_image_t; ++typedef void *rbd_completion_t; ++typedef void (*rbd_callback_t)(rbd_completion_t cb, void *arg); ++ ++typedef struct { ++ uint64_t id; ++ uint64_t size; ++ const char *name; ++} rbd_snap_info_t; ++ ++#define RBD_MAX_IMAGE_NAME_SIZE 96 ++#define RBD_MAX_BLOCK_NAME_SIZE 24 ++ ++typedef struct { ++ uint64_t size; ++ uint64_t obj_size; ++ uint64_t num_objs; ++ int order; ++ char block_name_prefix[RBD_MAX_BLOCK_NAME_SIZE]; ++ int64_t parent_pool; ++ char parent_name[RBD_MAX_IMAGE_NAME_SIZE]; ++} rbd_image_info_t; ++ ++static int (*rbd_create)(rados_ioctx_t io, const char *name, uint64_t size, ++ int *order); ++static int (*rbd_open)(rados_ioctx_t io, const char *name, rbd_image_t *image, ++ const char *snap_name); ++static int (*rbd_close)(rbd_image_t image); ++static int (*rbd_resize)(rbd_image_t image, uint64_t size); ++static int (*rbd_stat)(rbd_image_t image, rbd_image_info_t *info, ++ size_t infosize); ++static int (*rbd_snap_list)(rbd_image_t image, rbd_snap_info_t *snaps, ++ int *max_snaps); ++static void (*rbd_snap_list_end)(rbd_snap_info_t *snaps); ++static int (*rbd_snap_create)(rbd_image_t image, const char *snapname); ++static int (*rbd_snap_remove)(rbd_image_t image, const char *snapname); ++static int (*rbd_snap_rollback)(rbd_image_t image, const char *snapname); ++static int (*rbd_aio_write)(rbd_image_t image, uint64_t off, size_t len, ++ const char *buf, rbd_completion_t c); ++static int (*rbd_aio_read)(rbd_image_t image, uint64_t off, size_t len, ++ char *buf, rbd_completion_t c); ++static int (*rbd_aio_discard)(rbd_image_t image, uint64_t off, uint64_t len, ++ rbd_completion_t c); ++static int (*rbd_aio_create_completion)(void *cb_arg, ++ rbd_callback_t complete_cb, ++ rbd_completion_t *c); ++static ssize_t (*rbd_aio_get_return_value)(rbd_completion_t c); ++static void (*rbd_aio_release)(rbd_completion_t c); ++static int (*rbd_flush)(rbd_image_t image); ++static int (*rbd_aio_flush)(rbd_image_t image, rbd_completion_t c); ++ ++#endif +diff --git a/configure b/configure +index 4d1bc44..df587d7 100755 +--- a/configure ++++ b/configure +@@ -224,7 +224,6 @@ qom_cast_debug="yes" + trace_backend="nop" + trace_file="trace" + spice="" +-rbd="" + smartcard_nss="" + libusb="" + usb_redir="" +@@ -880,10 +879,6 @@ for opt do + ;; + --enable-glx) glx="yes" + ;; +- --disable-rbd) rbd="no" +- ;; +- --enable-rbd) rbd="yes" +- ;; + --disable-xfsctl) xfs="no" + ;; + --enable-xfsctl) xfs="yes" +@@ -1181,7 +1176,6 @@ echo " --with-trace-file=NAME Full PATH,NAME of file to store traces" + echo " Default:trace-" + echo " --disable-spice disable spice" + echo " --enable-spice enable spice" +-echo " --enable-rbd enable building the rados block device (rbd)" + echo " --disable-libiscsi disable iscsi support" + echo " --enable-libiscsi enable iscsi support" + echo " --disable-smartcard-nss disable smartcard nss support" +@@ -2250,10 +2244,10 @@ if test "$mingw32" = yes; then + else + glib_req_ver=2.12 + fi +-if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 > /dev/null 2>&1 ++if $pkg_config --atleast-version=$glib_req_ver gthread-2.0 gmodule-2.0 > /dev/null 2>&1 + then +- glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null` +- glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null` ++ glib_cflags=`$pkg_config --cflags gthread-2.0 gmodule-2.0 2>/dev/null` ++ glib_libs=`$pkg_config --libs gthread-2.0 gmodule-2.0 2>/dev/null` + LIBS="$glib_libs $LIBS" + libs_qga="$glib_libs $libs_qga" + else +@@ -2354,31 +2348,6 @@ if test "$mingw32" != yes -a "$pthread" = no; then + fi + + ########################################## +-# rbd probe +-if test "$rbd" != "no" ; then +- cat > $TMPC < +-#include +-int main(void) { +- rados_t cluster; +- rados_create(&cluster, NULL); +- return 0; +-} +-EOF +- rbd_libs="-lrbd -lrados" +- if compile_prog "" "$rbd_libs" ; then +- rbd=yes +- libs_tools="$rbd_libs $libs_tools" +- libs_softmmu="$rbd_libs $libs_softmmu" +- else +- if test "$rbd" = "yes" ; then +- feature_not_found "rados block device" +- fi +- rbd=no +- fi +-fi +- +-########################################## + # libssh2 probe + min_libssh2_version=1.2.8 + if test "$libssh2" != "no" ; then +@@ -3573,7 +3542,6 @@ echo "vhost-scsi support $vhost_scsi" + echo "Trace backend $trace_backend" + echo "Trace output file $trace_file-" + echo "spice support $spice ($spice_protocol_version/$spice_server_version)" +-echo "rbd support $rbd" + echo "xfsctl support $xfs" + echo "nss used $smartcard_nss" + echo "libusb $libusb" +@@ -3928,9 +3896,6 @@ fi + if test "$qom_cast_debug" = "yes" ; then + echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak + fi +-if test "$rbd" = "yes" ; then +- echo "CONFIG_RBD=y" >> $config_host_mak +-fi + + echo "CONFIG_COROUTINE_BACKEND=$coroutine" >> $config_host_mak + +-- +1.7.11.7 + diff --git a/SOURCES/kvm-rdma-export-qemu_fflush.patch b/SOURCES/kvm-rdma-export-qemu_fflush.patch new file mode 100644 index 0000000..de19f2c --- /dev/null +++ b/SOURCES/kvm-rdma-export-qemu_fflush.patch @@ -0,0 +1,66 @@ +From 4848a95daabaa6794869126afd7426b76653920f Mon Sep 17 00:00:00 2001 +From: Orit Wasserman +Date: Wed, 9 Oct 2013 10:09:08 +0200 +Subject: [PATCH 13/25] rdma: export qemu_fflush() + +RH-Author: Orit Wasserman +Message-id: <1381313355-15641-4-git-send-email-owasserm@redhat.com> +Patchwork-id: 54799 +O-Subject: [RHEL7.0 qemu-kvm v2 03/10] rdma: export qemu_fflush() +Bugzilla: 921465 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Juan Quintela + +From: "Michael R. Hines" + +RDMA uses this to flush the control channel before sending its +own message to handle page registrations. + +Reviewed-by: Juan Quintela +Reviewed-by: Paolo Bonzini +Reviewed-by: Chegu Vinod +Tested-by: Chegu Vinod +Tested-by: Michael R. Hines +Signed-off-by: Michael R. Hines +Signed-off-by: Juan Quintela +(cherry picked from commit be903b2ae7ca750bde2549432c5536087436cf49) +--- + include/migration/qemu-file.h | 1 + + savevm.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + include/migration/qemu-file.h | 1 + + savevm.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h +index 7519464..8931e16 100644 +--- a/include/migration/qemu-file.h ++++ b/include/migration/qemu-file.h +@@ -110,6 +110,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); ++void qemu_fflush(QEMUFile *f); + + static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) + { +diff --git a/savevm.c b/savevm.c +index 4e0fab6..d3bd0ec 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -608,7 +608,7 @@ static inline bool qemu_file_is_writable(QEMUFile *f) + * If there is writev_buffer QEMUFileOps it uses it otherwise uses + * put_buffer ops. + */ +-static void qemu_fflush(QEMUFile *f) ++void qemu_fflush(QEMUFile *f) + { + ssize_t ret = 0; + +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Drop-cfi.pflash01-and-isa-ide-device.patch b/SOURCES/kvm-rhel-Drop-cfi.pflash01-and-isa-ide-device.patch new file mode 100644 index 0000000..c24188e --- /dev/null +++ b/SOURCES/kvm-rhel-Drop-cfi.pflash01-and-isa-ide-device.patch @@ -0,0 +1,61 @@ +From f6852e27575e095269a47f434d318b5fc8822e0a Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 14:10:18 +0100 +Subject: [PATCH 48/81] rhel: Drop "cfi.pflash01" and "isa-ide" device + +RH-Author: Markus Armbruster +Message-id: <1383401418-4444-3-git-send-email-armbru@redhat.com> +Patchwork-id: 55269 +O-Subject: [PATCH 7.0 qemu-kvm 2/2] rhel: Drop "cfi.pflash01" and "isa-ide" device +Bugzilla: 1001076 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Alex Williamson + +From: Markus Armbruster + +We can drop a device from the build only when it isn't referenced from +code we build. References come in two forms: extern symbols, and qdev +driver names. + +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. + +Unresolved driver names get detected only at runtime, so we better be +extra careful. There is just one occurence of either driver name +outside the code dropped by this patch: "isa-ide" in hw/isa/pc87312.c. +Compiled only when CONFIG_PC87312 is enabled. It isn't in our build. + +"cfi.pflash01" is already no-user. Drop it anyway, because it's easy +and safe. + +Signed-off-by: Markus Armbruster +--- + default-configs/x86_64-softmmu.mak | 2 -- + 1 file changed, 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/x86_64-softmmu.mak | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index 05cc2a3..70d8bd9 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -17,11 +17,9 @@ CONFIG_FDC=y + CONFIG_ACPI=y + CONFIG_APM=y + CONFIG_I8257=y +-CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y + CONFIG_PIIX_PCI=y + CONFIG_I8259=y +-CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) + CONFIG_PCI_HOTPLUG=y + CONFIG_MC146818RTC=y +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Drop-isa-vga-device.patch b/SOURCES/kvm-rhel-Drop-isa-vga-device.patch new file mode 100644 index 0000000..a3e1d94 --- /dev/null +++ b/SOURCES/kvm-rhel-Drop-isa-vga-device.patch @@ -0,0 +1,63 @@ +From 2badec2441d95d693d7125d87fa8867f24f1ea9d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 15:05:06 +0100 +Subject: [PATCH 49/81] rhel: Drop "isa-vga" device + +RH-Author: Markus Armbruster +Message-id: <1383404707-6015-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55272 +O-Subject: [PATCH 7.0 qemu-kvm 1/2] rhel: Drop "isa-vga" device +Bugzilla: 1001088 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Alex Williamson + +From: Markus Armbruster + +We can drop a device from the build only when it isn't referenced from +code we build. References come in two forms: extern symbols, and qdev +driver names. + +Unresolved extern symbols pose no real danger, because they fail +safely at link time. The dropped code doesn't define any extern +symbols anyway. + +Unresolved driver names get detected only at runtime, so we better be +extra careful. Occurences of the driver name outside the code dropped +by this patch: + +* default_list[] in vl.c: Used only to disable default VGA with + -device isa-vga. Safe. + +* vga_available() in vl.c: Tests whether the device is compiled in. + No change, because device "VGA" is still compiled in, therfore safe. + +* isa_vga_init() in hw/isa/isa-bus.c: Its only potential caller + pc_vga_init() never calls in RHEL, because it never gets a null + pci_bus argument. Safe. + +Signed-off-by: Markus Armbruster +--- + default-configs/x86_64-softmmu.mak | 1 - + 1 file changed, 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/x86_64-softmmu.mak | 1 - + 1 files changed, 0 insertions(+), 1 deletions(-) + +diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak +index 70d8bd9..e7c48ec 100644 +--- a/default-configs/x86_64-softmmu.mak ++++ b/default-configs/x86_64-softmmu.mak +@@ -6,7 +6,6 @@ include usb.mak + CONFIG_VGA=y + CONFIG_QXL=$(CONFIG_SPICE) + CONFIG_VGA_PCI=y +-CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Drop-ivshmem-device.patch b/SOURCES/kvm-rhel-Drop-ivshmem-device.patch new file mode 100644 index 0000000..8a41e66 --- /dev/null +++ b/SOURCES/kvm-rhel-Drop-ivshmem-device.patch @@ -0,0 +1,60 @@ +From 987638b1d627c7f7234210c1dff1f7e795f3aae3 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 16:09:08 +0100 +Subject: [PATCH 13/29] rhel: Drop "ivshmem" device + +RH-Author: Markus Armbruster +Message-id: <1383408548-7760-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55277 +O-Subject: [PATCH 7.0 qemu-kvm 1/1] rhel: Drop "ivshmem" device +Bugzilla: 787463 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +We can drop a device from the build only when it isn't referenced from +code we build. References come in two forms: extern symbols, and qdev +driver names. + +Unresolved extern symbols pose no real danger, because they fail +safely at link time. But the dropped code doesn't define any extern +symbols anyway. + +Unresolved driver names get detected only at runtime, so we better be +extra careful. The only occurences of the driver name outside the +code dropped by this patch is in machine type compat properties +(safe), and those aren't even compiled for RHEL (extra safe). + +Since there's no CONFIG_IVSHMEM, we need to hack the Makefile +directly. Creating CONFIG_IVSHMEM upstream would be nice, but we're +out of time. + +Signed-off-by: Markus Armbruster +--- + hw/misc/Makefile.objs | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/Makefile.objs | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs +index 2578e29..cd3123b 100644 +--- a/hw/misc/Makefile.objs ++++ b/hw/misc/Makefile.objs +@@ -17,7 +17,8 @@ common-obj-$(CONFIG_PUV3) += puv3_pm.o + common-obj-$(CONFIG_MACIO) += macio/ + + ifeq ($(CONFIG_PCI), y) +-obj-$(CONFIG_KVM) += ivshmem.o ++# Disabled for Red Hat Enterprise Linux: ++# obj-$(CONFIG_KVM) += ivshmem.o + obj-$(CONFIG_LINUX) += vfio.o + endif + +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Make-ccid-card-emulated-device-unavailable.patch b/SOURCES/kvm-rhel-Make-ccid-card-emulated-device-unavailable.patch new file mode 100644 index 0000000..eb688e2 --- /dev/null +++ b/SOURCES/kvm-rhel-Make-ccid-card-emulated-device-unavailable.patch @@ -0,0 +1,48 @@ +From 92d723eb5a17c33f9b446f59ebc453c05614a6ac Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 15:24:00 +0100 +Subject: [PATCH 51/81] rhel: Make "ccid-card-emulated" device unavailable + +RH-Author: Markus Armbruster +Message-id: <1383405840-6221-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55273 +O-Subject: [PATCH 7.0 qemu-kvm 1/1] rhel: Make "ccid-card-emulated" device unavailable +Bugzilla: 1001123 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Alex Williamson + +From: Markus Armbruster + +We can't just --disable-smartcard-nss, because that also disables +libcacard. Instead, make it unavailable with -device / device_add. +Suffices, because there's no other way to get it: the device model +defines no external symbols, and the driver name doesn't occur in code +outside the device model. + +Signed-off-by: Markus Armbruster +--- + hw/usb/ccid-card-emulated.c | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/ccid-card-emulated.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c +index aa913df..037a9ec 100644 +--- a/hw/usb/ccid-card-emulated.c ++++ b/hw/usb/ccid-card-emulated.c +@@ -595,6 +595,8 @@ static void emulated_class_initfn(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + dc->desc = "emulated smartcard"; + dc->props = emulated_card_properties; ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo emulated_card_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Make-isa-cirrus-vga-device-unavailable.patch b/SOURCES/kvm-rhel-Make-isa-cirrus-vga-device-unavailable.patch new file mode 100644 index 0000000..8d5e608 --- /dev/null +++ b/SOURCES/kvm-rhel-Make-isa-cirrus-vga-device-unavailable.patch @@ -0,0 +1,51 @@ +From 76ec45c8db5e4654a02c296ce7bc610c5be60bdb Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 15:05:07 +0100 +Subject: [PATCH 50/81] rhel: Make "isa-cirrus-vga" device unavailable + +RH-Author: Markus Armbruster +Message-id: <1383404707-6015-3-git-send-email-armbru@redhat.com> +Patchwork-id: 55270 +O-Subject: [PATCH 7.0 qemu-kvm 2/2] rhel: Make "isa-cirrus-vga" device unavailable +Bugzilla: 1001088 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Alex Williamson + +From: Markus Armbruster + +We can't drop it, because the ISA device is entangled with the PCI +device, which we want to keep. Disentangling it upstream would be +nice, but we're out of time. + +Instead, make it unavailable with -device / device_add. Suffices, +because the only other way to get it is via pc_vga_init() calling +isa_vga_init(), which it never does in RHEL, because it never gets a +null pci_bus argument. + +Signed-off-by: Markus Armbruster +--- + hw/display/cirrus_vga.c | 2 ++ + 1 file changed, 2 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/display/cirrus_vga.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index a7634ba..bfaa0b0 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -2937,6 +2937,8 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) + k->init = vga_initfn; + dc->props = isa_cirrus_vga_properties; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo isa_cirrus_vga_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Make-pci-serial-2x-and-pci-serial-4x-device-una.patch b/SOURCES/kvm-rhel-Make-pci-serial-2x-and-pci-serial-4x-device-una.patch new file mode 100644 index 0000000..b3f2409 --- /dev/null +++ b/SOURCES/kvm-rhel-Make-pci-serial-2x-and-pci-serial-4x-device-una.patch @@ -0,0 +1,57 @@ +From 300a7cf7103f2bad1767dbb9f4a805bb2199fb7f Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 15:39:00 +0100 +Subject: [PATCH 62/81] rhel: Make "pci-serial-2x" and "pci-serial-4x" device unavailable + +RH-Author: Markus Armbruster +Message-id: <1383406740-6461-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55276 +O-Subject: [PATCH 7.0 qemu-kvm 1/1] rhel: Make "pci-serial-2x" and "pci-serial-4x" device unavailable +Bugzilla: 1001180 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Markus Armbruster + +We can't just drop CONFIG_SERIAL_PCI, because we still want +"pci-serial". Instead, make them unavailable with -device / +device_add. Suffices, because there's no other way to get it: the +device model defines no external symbols, and the driver name doesn't +occur in code outside the device model. + +Signed-off-by: Markus Armbruster +--- + hw/char/serial-pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/char/serial-pci.c | 4 ++++ + 1 files changed, 4 insertions(+), 0 deletions(-) + +diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c +index 77fec01..bfe686b 100644 +--- a/hw/char/serial-pci.c ++++ b/hw/char/serial-pci.c +@@ -207,6 +207,8 @@ static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_2x_serial_pci_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) +@@ -222,6 +224,8 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_pci_multi_serial; + dc->props = multi_4x_serial_pci_properties; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo serial_pci_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Revert-downstream-changes-to-unused-default-con.patch b/SOURCES/kvm-rhel-Revert-downstream-changes-to-unused-default-con.patch new file mode 100644 index 0000000..8fac221 --- /dev/null +++ b/SOURCES/kvm-rhel-Revert-downstream-changes-to-unused-default-con.patch @@ -0,0 +1,254 @@ +From a73d17d9798440ecd0c6bc45a016093fddfea944 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 14:10:17 +0100 +Subject: [PATCH 47/81] rhel: Revert downstream changes to unused default-configs/*.mak + +RH-Author: Markus Armbruster +Message-id: <1383401418-4444-2-git-send-email-armbru@redhat.com> +Patchwork-id: 55268 +O-Subject: [PATCH 7.0 qemu-kvm 1/2] rhel: Revert downstream changes to unused default-configs/*.mak +Bugzilla: 1001076 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Alex Williamson + +From: Markus Armbruster + +Pointless conflict magnets. "Unused" means they don't affect the RHEL +build in any way. + +Signed-off-by: Markus Armbruster +--- + default-configs/alpha-softmmu.mak | 1 + + default-configs/i386-softmmu.mak | 5 +++++ + default-configs/mips-softmmu.mak | 3 +++ + default-configs/mips64-softmmu.mak | 3 +++ + default-configs/mips64el-softmmu.mak | 3 +++ + default-configs/mipsel-softmmu.mak | 3 +++ + default-configs/ppc-softmmu.mak | 2 ++ + default-configs/ppc64-softmmu.mak | 2 ++ + default-configs/ppcemb-softmmu.mak | 1 + + default-configs/sparc-softmmu.mak | 1 + + default-configs/sparc64-softmmu.mak | 1 + + 11 files changed, 25 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + default-configs/alpha-softmmu.mak | 1 + + default-configs/i386-softmmu.mak | 5 +++++ + default-configs/mips-softmmu.mak | 3 +++ + default-configs/mips64-softmmu.mak | 3 +++ + default-configs/mips64el-softmmu.mak | 3 +++ + default-configs/mipsel-softmmu.mak | 3 +++ + default-configs/ppc-softmmu.mak | 2 ++ + default-configs/ppc64-softmmu.mak | 2 ++ + default-configs/ppcemb-softmmu.mak | 1 + + default-configs/sparc-softmmu.mak | 1 + + default-configs/sparc64-softmmu.mak | 1 + + 11 files changed, 25 insertions(+), 0 deletions(-) + +diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak +index f2792ad..18e5337 100644 +--- a/default-configs/alpha-softmmu.mak ++++ b/default-configs/alpha-softmmu.mak +@@ -10,6 +10,7 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_CIRRUS=y + CONFIG_IDE_CORE=y + CONFIG_IDE_QDEV=y ++CONFIG_VMWARE_VGA=y + CONFIG_IDE_CMD646=y + CONFIG_I8259=y + CONFIG_MC146818RTC=y +diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak +index 54df7bd..03deca2 100644 +--- a/default-configs/i386-softmmu.mak ++++ b/default-configs/i386-softmmu.mak +@@ -8,8 +8,10 @@ CONFIG_QXL=$(CONFIG_SPICE) + CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y + CONFIG_VMMOUSE=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +@@ -19,7 +21,10 @@ CONFIG_APM=y + CONFIG_I8257=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y ++CONFIG_NE2000_ISA=y + CONFIG_PIIX_PCI=y ++CONFIG_HPET=y ++CONFIG_APPLESMC=y + CONFIG_I8259=y + CONFIG_PFLASH_CFI01=y + CONFIG_TPM_TIS=$(CONFIG_TPM) +diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak +index b4eef8c..b443702 100644 +--- a/default-configs/mips-softmmu.mak ++++ b/default-configs/mips-softmmu.mak +@@ -10,7 +10,9 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +@@ -21,6 +23,7 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y ++CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak +index c7a9232..d638957 100644 +--- a/default-configs/mips64-softmmu.mak ++++ b/default-configs/mips64-softmmu.mak +@@ -10,7 +10,9 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +@@ -21,6 +23,7 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y ++CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak +index 79bdfdb..c9be3f4 100644 +--- a/default-configs/mips64el-softmmu.mak ++++ b/default-configs/mips64el-softmmu.mak +@@ -10,7 +10,9 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +@@ -22,6 +24,7 @@ CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y + CONFIG_IDE_VIA=y ++CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak +index beb6819..4f4a449 100644 +--- a/default-configs/mipsel-softmmu.mak ++++ b/default-configs/mipsel-softmmu.mak +@@ -10,7 +10,9 @@ CONFIG_VGA_PCI=y + CONFIG_VGA_ISA=y + CONFIG_VGA_ISA_MM=y + CONFIG_VGA_CIRRUS=y ++CONFIG_VMWARE_VGA=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCSPK=y + CONFIG_PCKBD=y +@@ -21,6 +23,7 @@ CONFIG_I8257=y + CONFIG_PIIX4=y + CONFIG_IDE_ISA=y + CONFIG_IDE_PIIX=y ++CONFIG_NE2000_ISA=y + CONFIG_RC4030=y + CONFIG_DP8393X=y + CONFIG_DS1225Y=y +diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak +index 7f6ea0f..cc3587f 100644 +--- a/default-configs/ppc-softmmu.mak ++++ b/default-configs/ppc-softmmu.mak +@@ -10,6 +10,7 @@ CONFIG_M48T59=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCKBD=y + CONFIG_FDC=y +@@ -33,6 +34,7 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y ++CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak +index 29a8be6..884ea8a 100644 +--- a/default-configs/ppc64-softmmu.mak ++++ b/default-configs/ppc64-softmmu.mak +@@ -10,6 +10,7 @@ CONFIG_M48T59=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_I8254=y + CONFIG_PCKBD=y + CONFIG_FDC=y +@@ -33,6 +34,7 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y ++CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak +index a8ab6e3..be93e03 100644 +--- a/default-configs/ppcemb-softmmu.mak ++++ b/default-configs/ppcemb-softmmu.mak +@@ -29,6 +29,7 @@ CONFIG_PPCE500_PCI=y + CONFIG_IDE_ISA=y + CONFIG_IDE_CMD646=y + CONFIG_IDE_MACIO=y ++CONFIG_NE2000_ISA=y + CONFIG_PFLASH_CFI01=y + CONFIG_PFLASH_CFI02=y + CONFIG_PTIMER=y +diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak +index ddba71d..8fc93dd 100644 +--- a/default-configs/sparc-softmmu.mak ++++ b/default-configs/sparc-softmmu.mak +@@ -7,6 +7,7 @@ CONFIG_M48T59=y + CONFIG_PTIMER=y + CONFIG_FDC=y + CONFIG_EMPTY_SLOT=y ++CONFIG_PCNET_COMMON=y + CONFIG_LANCE=y + CONFIG_TCX=y + CONFIG_SLAVIO=y +diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak +index 2998f34..9b08ee8 100644 +--- a/default-configs/sparc64-softmmu.mak ++++ b/default-configs/sparc64-softmmu.mak +@@ -8,6 +8,7 @@ CONFIG_PTIMER=y + CONFIG_VGA=y + CONFIG_VGA_PCI=y + CONFIG_SERIAL=y ++CONFIG_PARALLEL=y + CONFIG_PCKBD=y + CONFIG_FDC=y + CONFIG_IDE_ISA=y +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-Revert-unwanted-cannot_instantiate_with_device_.patch b/SOURCES/kvm-rhel-Revert-unwanted-cannot_instantiate_with_device_.patch new file mode 100644 index 0000000..7744eea --- /dev/null +++ b/SOURCES/kvm-rhel-Revert-unwanted-cannot_instantiate_with_device_.patch @@ -0,0 +1,117 @@ +From 782eba126f0af8ccbb3625fe1ac1d92bf923a10d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:22 +0100 +Subject: [PATCH 46/81] rhel: Revert unwanted cannot_instantiate_with_device_add_yet changes + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-18-git-send-email-kwolf@redhat.com> +Patchwork-id: 55543 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 17/17] rhel: Revert unwanted cannot_instantiate_with_device_add_yet changes +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +The no-user series just backported from upstream makes the following +onboard devices also available with -device / device_add: + +* PCI [PATCH 07-08]: piix3-ide, piix3-ide-xen, piix4-ide, via-ide +* ISA [PATCH 09]: i8042, isa-fdc + +Not wanted for RHEL, so revert that part. + +Note: via-ide just for consistency; we don't actually compile it. + +Signed-off-by: Markus Armbruster +Signed-off-by: Kevin Wolf +--- + hw/block/fdc.c | 2 ++ + hw/ide/piix.c | 6 ++++++ + hw/ide/via.c | 2 ++ + hw/input/pckbd.c | 2 ++ + 4 files changed, 12 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/block/fdc.c | 2 ++ + hw/ide/piix.c | 6 ++++++ + hw/ide/via.c | 2 ++ + hw/input/pckbd.c | 2 ++ + 4 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/hw/block/fdc.c b/hw/block/fdc.c +index f3b5bec..322d863 100644 +--- a/hw/block/fdc.c ++++ b/hw/block/fdc.c +@@ -2210,6 +2210,8 @@ static void isabus_fdc_class_init(ObjectClass *klass, void *data) + dc->vmsd = &vmstate_isa_fdc; + dc->props = isa_fdc_properties; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo isa_fdc_info = { +diff --git a/hw/ide/piix.c b/hw/ide/piix.c +index 304cab0..1757ae0 100644 +--- a/hw/ide/piix.c ++++ b/hw/ide/piix.c +@@ -249,6 +249,8 @@ static void piix3_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix3_ide_info = { +@@ -269,6 +271,8 @@ static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); + dc->unplug = pci_piix3_xen_ide_unplug; ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix3_ide_xen_info = { +@@ -290,6 +294,8 @@ static void piix4_ide_class_init(ObjectClass *klass, void *data) + k->device_id = PCI_DEVICE_ID_INTEL_82371AB; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo piix4_ide_info = { +diff --git a/hw/ide/via.c b/hw/ide/via.c +index 326722c..30bdc60 100644 +--- a/hw/ide/via.c ++++ b/hw/ide/via.c +@@ -224,6 +224,8 @@ static void via_ide_class_init(ObjectClass *klass, void *data) + k->revision = 0x06; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo via_ide_info = { +diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c +index ed396bf..850a92c 100644 +--- a/hw/input/pckbd.c ++++ b/hw/input/pckbd.c +@@ -515,6 +515,8 @@ static void i8042_class_initfn(ObjectClass *klass, void *data) + ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); + ic->init = i8042_initfn; + dc->vmsd = &vmstate_kbd_isa; ++ /* Disabled for Red Hat Enterprise Linux: */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo i8042_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel-SMBIOS-type-1-branding.patch b/SOURCES/kvm-rhel-SMBIOS-type-1-branding.patch new file mode 100644 index 0000000..d500d40 --- /dev/null +++ b/SOURCES/kvm-rhel-SMBIOS-type-1-branding.patch @@ -0,0 +1,83 @@ +From 13f5bfee8de72bc90324d84cba85850c66c001ed Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:28 +0100 +Subject: [PATCH 28/29] rhel: SMBIOS type 1 branding + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-12-git-send-email-armbru@redhat.com> +Patchwork-id: 55242 +O-Subject: [PATCH 7.0 qemu-kvm 11/11] rhel: SMBIOS type 1 branding +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +The previous two commits got us the upstreamable parts of RHEL-6 +commit 68c63bd "per-machine-type smbios Type 1 smbios values". This +is the RHEL-only part. + +Note: RHEL-6 also has commit 8e0d71e "Set SMBIOS vendor to QEMU for +RHEL5 machine types.", which RHEL-7 doesn't need, because it doesn't +have RHEL-5 machine types. + +Signed-off-by: Markus Armbruster +--- + hw/i386/pc_piix.c | 3 +-- + hw/i386/pc_q35.c | 3 +-- + hw/i386/smbios.c | 3 +++ + 3 files changed, 5 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 3 +-- + hw/i386/pc_q35.c | 3 +-- + hw/i386/smbios.c | 3 +++ + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 396f4e4..825a5b1 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -117,8 +117,7 @@ static void pc_init1(QEMUMachineInitArgs *args, + + if (smbios_type1_defaults) { + /* These values are guest ABI, do not change */ +- smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", +- args->machine->name); ++ smbios_set_type1_defaults("Red Hat", "KVM", args->machine->desc); + } + + /* allocate ram and load rom/bios */ +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 473f01b..64995ac 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -103,8 +103,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + + if (smbios_type1_defaults) { + /* These values are guest ABI, do not change */ +- smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", +- args->machine->name); ++ smbios_set_type1_defaults("Red Hat", "KVM", args->machine->desc); + } + + /* allocate ram and load rom/bios */ +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index e8f41ad..60aa62e 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -268,6 +268,9 @@ void smbios_set_type1_defaults(const char *manufacturer, + if (!type1.version) { + type1.version = version; + } ++ if (!type1.family) { ++ type1.family = "Red Hat Enterprise Linux"; ++ } + } + + uint8_t *smbios_get_table(size_t *length) +-- +1.7.1 + diff --git a/SOURCES/kvm-rhel6-compat-usb-serial-numbers.patch b/SOURCES/kvm-rhel6-compat-usb-serial-numbers.patch new file mode 100644 index 0000000..9feec6c --- /dev/null +++ b/SOURCES/kvm-rhel6-compat-usb-serial-numbers.patch @@ -0,0 +1,95 @@ +From c1565b1a48db60bb86d83ec00c86b6ddfaf12d62 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 2 Sep 2013 13:26:16 +0200 +Subject: [PATCH 10/29] rhel6 compat: usb serial numbers + +RH-Author: Gerd Hoffmann +Message-id: <1378128376-25930-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 53987 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/2] rhel6 compat: usb serial numbers +Bugzilla: 953304 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Hans de Goede +RH-Acked-by: Paolo Bonzini + +Add serial number compat properties to the rhel6 machine types, +to match rhel6 behavior. Two things we have to watch out here: + +First the HID devices flipped serial from "1" to "42" to indicate +remote wakeup capability, in RHEL-6.2. + +rhel6 commit 85ae0a096fdbc4a6f5a660bf60a74c092f9c0f7a + +Second devices get unique serial numbers, by appending host adapter +pci address and port path, in RHEL-6.4, for usb-hub and usb-storage. +Also usb-net + usb-serial + usb-wacom, but those are disabled in RHEL. + +rhel6 commit e91156bc452250291f72b82b43654540be7101be + +usb-ccid has a unique serial in RHEL-7 but not in RHEL-6, so we need +a compat property for all RHEL-6.x machine types. + +bugzilla: 953304 + +Signed-off-by: Gerd Hoffmann +--- + hw/i386/pc_piix.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 24 ++++++++++++++++++++++++ + 1 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index da7701c..a19f155 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -860,6 +860,10 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "486-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(0),\ ++ },{\ ++ .driver = "usb-ccid",\ ++ .property = "serial",\ ++ .value = "1",\ + } + + static void pc_init_rhel650(QEMUMachineInitArgs *args) +@@ -959,6 +963,14 @@ static QEMUMachine pc_machine_rhel640 = { + .driver = TYPE_X86_CPU,\ + .property = "pmu",\ + .value = "on",\ ++ },{\ ++ .driver = "usb-hub",\ ++ .property = "serial",\ ++ .value = "314159",\ ++ },{\ ++ .driver = "usb-storage",\ ++ .property = "serial",\ ++ .value = "1",\ + } + + static void pc_init_rhel630(QEMUMachineInitArgs *args) +@@ -1041,6 +1053,18 @@ static QEMUMachine pc_machine_rhel620 = { + .driver = "virtio-balloon-pci",\ + .property = "event_idx",\ + .value = "off",\ ++ },{\ ++ .driver = "usb-kbd",\ ++ .property = "serial",\ ++ .value = "1",\ ++ },{\ ++ .driver = "usb-mouse",\ ++ .property = "serial",\ ++ .value = "1",\ ++ },{\ ++ .driver = "usb-tablet",\ ++ .property = "serial",\ ++ .value = "1",\ + } + + static void pc_init_rhel610(QEMUMachineInitArgs *args) +-- +1.7.1 + diff --git a/SOURCES/kvm-rng-random-use-error_setg_file_open.patch b/SOURCES/kvm-rng-random-use-error_setg_file_open.patch new file mode 100644 index 0000000..9a72315 --- /dev/null +++ b/SOURCES/kvm-rng-random-use-error_setg_file_open.patch @@ -0,0 +1,47 @@ +From bfff0a4af270437508a38f1795e87ff293c4f9d4 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:24 +0100 +Subject: [PATCH 05/29] rng-random: use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-2-git-send-email-lersek@redhat.com> +Patchwork-id: 55191 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/8] rng-random: use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit bc5741add11113ee8febdcf33931ec3afe10c729) +Signed-off-by: Laszlo Ersek +--- + backends/rng-random.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + backends/rng-random.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/backends/rng-random.c b/backends/rng-random.c +index 830360c..68dfc8a 100644 +--- a/backends/rng-random.c ++++ b/backends/rng-random.c +@@ -78,9 +78,8 @@ static void rng_random_opened(RngBackend *b, Error **errp) + "filename", "a valid filename"); + } else { + s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK); +- + if (s->fd == -1) { +- error_set(errp, QERR_OPEN_FILE_FAILED, s->filename); ++ error_setg_file_open(errp, errno, s->filename); + } + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-savevm-qmp_xen_save_devices_state-use-error_setg_fil.patch b/SOURCES/kvm-savevm-qmp_xen_save_devices_state-use-error_setg_fil.patch new file mode 100644 index 0000000..d1c7451 --- /dev/null +++ b/SOURCES/kvm-savevm-qmp_xen_save_devices_state-use-error_setg_fil.patch @@ -0,0 +1,45 @@ +From 1cb04a74ed9b2f4a05ac21ce1e9a5ca884c9b97e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 31 Oct 2013 16:29:29 +0100 +Subject: [PATCH 10/29] savevm: qmp_xen_save_devices_state(): use error_setg_file_open() + +RH-Author: Laszlo Ersek +Message-id: <1383236971-6067-7-git-send-email-lersek@redhat.com> +Patchwork-id: 55196 +O-Subject: [RHEL-7 qemu-kvm PATCH 6/8] savevm: qmp_xen_save_devices_state(): use error_setg_file_open() +Bugzilla: 907743 +RH-Acked-by: Luiz Capitulino +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini + +From: Luiz Capitulino + +Signed-off-by: Luiz Capitulino +Acked-by: Kevin Wolf +(cherry picked from commit 1befce9652a1b7cfca0191b3031fae3cbce26ef0) +Signed-off-by: Laszlo Ersek +--- + savevm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + savevm.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/savevm.c b/savevm.c +index d3bd0ec..1ed7f05 100644 +--- a/savevm.c ++++ b/savevm.c +@@ -2419,7 +2419,7 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp) + + f = qemu_fopen(filename, "wb"); + if (!f) { +- error_set(errp, QERR_OPEN_FILE_FAILED, filename); ++ error_setg_file_open(errp, errno, filename); + goto the_end; + } + ret = qemu_save_device_state(f); +-- +1.7.1 + diff --git a/SOURCES/kvm-scsi-Fix-scsi_bus_legacy_add_drive-scsi-generic-with.patch b/SOURCES/kvm-scsi-Fix-scsi_bus_legacy_add_drive-scsi-generic-with.patch new file mode 100644 index 0000000..8f4bff2 --- /dev/null +++ b/SOURCES/kvm-scsi-Fix-scsi_bus_legacy_add_drive-scsi-generic-with.patch @@ -0,0 +1,65 @@ +From 284ff94d1e2c50f7314d5a60e0a45d6710160420 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 30 Sep 2013 12:03:39 +0200 +Subject: [PATCH 09/25] scsi: Fix scsi_bus_legacy_add_drive() scsi-generic with serial +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <1380542619-20274-2-git-send-email-armbru@redhat.com> +Patchwork-id: 54583 +O-Subject: [PATCH 7.0 qemu-kvm 1/1] scsi: Fix scsi_bus_legacy_add_drive() scsi-generic with serial +Bugzilla: 1009285 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +scsi_bus_legacy_add_drive() creates either a scsi-disk or a +scsi-generic device. It sets property "serial" to argument serial +unless null. Crashes with scsi-generic, because it doesn't have such +the property. + +Only usb_msd_initfn_storage() passes non-null serial. Reproducer: + + $ qemu-system-x86_64 -nodefaults -display none -S -usb \ + -drive if=none,file=/dev/sg1,id=usb-drv0 \ + -device usb-storage,id=usb-msd0,drive=usb-drv0,serial=123 + qemu-system-x86_64: -device usb-storage,id=usb-msd0,drive=usb-drv0,serial=123: Property '.serial' not found + Aborted (core dumped) + +Fix by handling exactly like "removable": set the property only when +it exists. + +Cc: qemu-stable@nongnu.org +Reviewed-by: Andreas Färber +Signed-off-by: Markus Armbruster +Signed-off-by: Paolo Bonzini +(cherry picked from commit c24e7517ee4a98e90eee5f0f07708a1fa12326b3) +--- + hw/scsi/scsi-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/scsi/scsi-bus.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 53ea906..0885d9d 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -223,7 +223,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, + if (object_property_find(OBJECT(dev), "removable", NULL)) { + qdev_prop_set_bit(dev, "removable", removable); + } +- if (serial) { ++ if (serial && object_property_find(OBJECT(dev), "serial", NULL)) { + qdev_prop_set_string(dev, "serial", serial); + } + if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { +-- +1.7.1 + diff --git a/SOURCES/kvm-scsi-prefer-UUID-to-VM-name-for-the-initiator-name.patch b/SOURCES/kvm-scsi-prefer-UUID-to-VM-name-for-the-initiator-name.patch new file mode 100644 index 0000000..442ead1 --- /dev/null +++ b/SOURCES/kvm-scsi-prefer-UUID-to-VM-name-for-the-initiator-name.patch @@ -0,0 +1,140 @@ +From ca89af18d37afb4fe9cea6e4ff3e22386d0db5b0 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 23 Sep 2013 17:07:53 +0200 +Subject: [PATCH 2/3] scsi: prefer UUID to VM name for the initiator name + +RH-Author: Paolo Bonzini +Message-id: <1379956073-3496-1-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54488 +O-Subject: [RHEL 7.0 qemu-kvm PATCH] scsi: prefer UUID to VM name for the initiator name +Bugzilla: 1006468 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Amos Kong + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1006468 + +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6317378 + +The UUID is unique even across multiple hosts, thus it is +better than a VM name even if it is less user-friendly. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 5accc8408f2dac1e00d888e4fe75e6174ba2a940) +--- + block/iscsi.c | 23 ++++++++++++++++------- + include/sysemu/sysemu.h | 2 ++ + stubs/Makefile.objs | 1 + + stubs/uuid.c | 12 ++++++++++++ + 4 files changed, 31 insertions(+), 7 deletions(-) + create mode 100644 stubs/uuid.c + +Signed-off-by: Miroslav Rezanina +--- + block/iscsi.c | 23 ++++++++++++++++------- + include/sysemu/sysemu.h | 2 ++ + stubs/Makefile.objs | 1 + + stubs/uuid.c | 12 ++++++++++++ + 4 files changed, 31 insertions(+), 7 deletions(-) + create mode 100644 stubs/uuid.c + +diff --git a/block/iscsi.c b/block/iscsi.c +index 1294fdf..4ab9edc 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -33,6 +33,8 @@ + #include "trace.h" + #include "block/scsi.h" + #include "qemu/iov.h" ++#include "sysemu/sysemu.h" ++#include "qmp-commands.h" + + #include + #include +@@ -923,8 +925,9 @@ static char *parse_initiator_name(const char *target) + { + QemuOptsList *list; + QemuOpts *opts; +- const char *name = NULL; +- const char *iscsi_name = qemu_get_vm_name(); ++ const char *name; ++ char *iscsi_name; ++ UuidInfo *uuid_info; + + list = qemu_find_opts("iscsi"); + if (list) { +@@ -934,16 +937,22 @@ static char *parse_initiator_name(const char *target) + } + if (opts) { + name = qemu_opt_get(opts, "initiator-name"); ++ if (name) { ++ return g_strdup(name); ++ } + } + } + +- if (name) { +- return g_strdup(name); ++ uuid_info = qmp_query_uuid(NULL); ++ if (strcmp(uuid_info->UUID, UUID_NONE) == 0) { ++ name = qemu_get_vm_name(); + } else { +- return g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s", +- iscsi_name ? ":" : "", +- iscsi_name ? iscsi_name : ""); ++ name = uuid_info->UUID; + } ++ iscsi_name = g_strdup_printf("iqn.2008-11.org.linux-kvm%s%s", ++ name ? ":" : "", name ? name : ""); ++ qapi_free_UuidInfo(uuid_info); ++ return iscsi_name; + } + + #if defined(LIBISCSI_FEATURE_NOP_COUNTER) +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index d7a77b6..76c5b64 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -17,7 +17,9 @@ extern const char *bios_name; + extern const char *qemu_name; + extern uint8_t qemu_uuid[]; + int qemu_uuid_parse(const char *str, uint8_t *uuid); ++ + #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" ++#define UUID_NONE "00000000-0000-0000-0000-000000000000" + + bool runstate_check(RunState state); + void runstate_set(RunState new_state); +diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs +index 9b701b4..4b2cb7d 100644 +--- a/stubs/Makefile.objs ++++ b/stubs/Makefile.objs +@@ -21,6 +21,7 @@ stub-obj-y += reset.o + stub-obj-y += set-fd-handler.o + stub-obj-y += slirp.o + stub-obj-y += sysbus.o ++stub-obj-y += uuid.o + stub-obj-y += vm-stop.o + stub-obj-y += vmstate.o + stub-obj-$(CONFIG_WIN32) += fd-register.o +diff --git a/stubs/uuid.c b/stubs/uuid.c +new file mode 100644 +index 0000000..ffc0ed4 +--- /dev/null ++++ b/stubs/uuid.c +@@ -0,0 +1,12 @@ ++#include "qemu-common.h" ++#include "sysemu/sysemu.h" ++#include "qmp-commands.h" ++ ++UuidInfo *qmp_query_uuid(Error **errp) ++{ ++ UuidInfo *info = g_malloc0(sizeof(*info)); ++ ++ info->UUID = g_strdup(UUID_NONE); ++ return info; ++} ++ +-- +1.7.1 + diff --git a/SOURCES/kvm-sd-Avoid-access-to-NULL-BlockDriverState.patch b/SOURCES/kvm-sd-Avoid-access-to-NULL-BlockDriverState.patch new file mode 100644 index 0000000..162590e --- /dev/null +++ b/SOURCES/kvm-sd-Avoid-access-to-NULL-BlockDriverState.patch @@ -0,0 +1,58 @@ +From 6c6316c53a1e2ddd34c31ecf5d757646482c4202 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Tue, 5 Nov 2013 14:09:15 +0100 +Subject: [PATCH 62/87] sd: Avoid access to NULL BlockDriverState +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <1383660558-32096-22-git-send-email-kwolf@redhat.com> +Patchwork-id: 55400 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 21/24] sd: Avoid access to NULL BlockDriverState +Bugzilla: 978402 +RH-Acked-by: Fam Zheng +RH-Acked-by: Max Reitz +RH-Acked-by: Laszlo Ersek + +From: Andreas Färber + +Commit 4f8a066b5fc254eeaabbbde56ba4f5b29cc68fdf (blockdev: Remove IF_* +check for read-only blockdev_init) added a usage of bdrv_is_read_only() +to sd_init(), which is called for versatilepb, versatileab and +xilinx-zynq-a9 machines among others with NULL argument by default, +causing the new qom-test to fail. + +Add a check to prevent this. + +Suggested-by: Kevin Wolf +Signed-off-by: Andreas Färber +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 794cbc26eb94ce13c75d105eea9ff0afff56e2c2) + +Signed-off-by: Kevin Wolf +--- + hw/sd/sd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/sd/sd.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index e816c78..c9651b9 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -492,7 +492,7 @@ SDState *sd_init(BlockDriverState *bs, bool is_spi) + { + SDState *sd; + +- if (bdrv_is_read_only(bs)) { ++ if (bs && bdrv_is_read_only(bs)) { + fprintf(stderr, "sd_init: Cannot use read-only drive\n"); + return NULL; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-seabios-paravirt-allow-more-than-1TB-in-x86-guest.patch b/SOURCES/kvm-seabios-paravirt-allow-more-than-1TB-in-x86-guest.patch new file mode 100644 index 0000000..58edd85 --- /dev/null +++ b/SOURCES/kvm-seabios-paravirt-allow-more-than-1TB-in-x86-guest.patch @@ -0,0 +1,43 @@ +From df701ea37b50b14a18185708189d85d332b29319 Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli +Date: Tue, 8 Oct 2013 17:05:45 +0200 +Subject: [PATCH 1/3] seabios paravirt: allow more than 1TB in x86 guest + +RH-Author: Andrea Arcangeli +Message-id: <1381251945-13402-2-git-send-email-aarcange@redhat.com> +Patchwork-id: 54784 +O-Subject: [RHEL-7.0 qemu-kvm PATCH] seabios paravirt: allow more than 1TB in x86 guest +Bugzilla: 989677 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gleb Natapov +RH-Acked-by: Laszlo Ersek + +This patch should be applied to the qemu-kvm rpm package at the same +time of the other one for seabios, so qemu will forward the ram_size +bits over 40 to seabios without losing them. + +Signed-off-by: Andrea Arcangeli +--- + hw/i386/pc.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 3c77040..d3acbbb 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -399,6 +399,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, + rtc_set_memory(s, 0x5b, val); + rtc_set_memory(s, 0x5c, val >> 8); + rtc_set_memory(s, 0x5d, val >> 16); ++ rtc_set_memory(s, 0x5e, val >> 24); + + /* set the number of CPU */ + rtc_set_memory(s, 0x5f, smp_cpus - 1); +-- +1.7.1 + diff --git a/SOURCES/kvm-seccomp-fine-tuning-whitelist-by-adding-times.patch b/SOURCES/kvm-seccomp-fine-tuning-whitelist-by-adding-times.patch new file mode 100644 index 0000000..9c22506 --- /dev/null +++ b/SOURCES/kvm-seccomp-fine-tuning-whitelist-by-adding-times.patch @@ -0,0 +1,56 @@ +From e95603940674bdb0d59c58f9a7fac3ea97c56d88 Mon Sep 17 00:00:00 2001 +From: Paul Moore +Date: Wed, 2 Oct 2013 20:09:33 +0200 +Subject: [PATCH 10/25] seccomp: fine tuning whitelist by adding times() + +RH-Author: Paul Moore +Message-id: <20131002200933.4639.16090.stgit@localhost> +Patchwork-id: 54645 +O-Subject: [RHEL7 qemu-kvm PATCH] seccomp: fine tuning whitelist by adding times() +Bugzilla: 1004175 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Luiz Capitulino + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1004175 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6362319 +Upstream: In QEMU/seccomp maintainer's tree + git://github.com/otubo/qemu.git#seccomp +Tested: Tested by myself, IBM, and original BZ reporter; see BZ. + + commit: c236f4519c9838801798f3705c17dce9ab9e3b9d + From: Eduardo Otubo + Date: 2013-09-04 09:21:12 -0300 + + seccomp: fine tuning whitelist by adding times() + + This was causing Qemu process to hang when using -sandbox on as + discribed on RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1004175 + + Signed-off-by: Eduardo Otubo + Tested-by: Paul Moore + Acked-by: Paul Moore +--- + qemu-seccomp.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + qemu-seccomp.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/qemu-seccomp.c b/qemu-seccomp.c +index 9e91c73..ca15f21 100644 +--- a/qemu-seccomp.c ++++ b/qemu-seccomp.c +@@ -98,6 +98,7 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { + { SCMP_SYS(getuid), 245 }, + { SCMP_SYS(geteuid), 245 }, + { SCMP_SYS(timer_create), 245 }, ++ { SCMP_SYS(times), 245 }, + { SCMP_SYS(exit), 245 }, + { SCMP_SYS(clock_gettime), 245 }, + { SCMP_SYS(time), 245 }, +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Convert-to-QemuOpts.patch b/SOURCES/kvm-smbios-Convert-to-QemuOpts.patch new file mode 100644 index 0000000..8b045e5 --- /dev/null +++ b/SOURCES/kvm-smbios-Convert-to-QemuOpts.patch @@ -0,0 +1,408 @@ +From 6a4b96232747a7e7319115a532f17913da6a7774 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:21 +0100 +Subject: [PATCH 21/29] smbios: Convert to QemuOpts + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-5-git-send-email-armbru@redhat.com> +Patchwork-id: 55240 +O-Subject: [PATCH 7.0 qemu-kvm 04/11] smbios: Convert to QemuOpts +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +So that it can be set in config file for -readconfig. + +This tightens parsing of -smbios, and makes it more consistent with +other options: unknown parameters are rejected, numbers with trailing +junk are rejected, when a parameter is given multiple times, last +rather than first wins, ... + +MST: drop one chunk to fix build errors + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 4f953d2fc806f1ba6fa76f01dfd121fe7d0dc4a7) +--- + arch_init.c | 4 +- + hw/i386/smbios.c | 209 ++++++++++++++++++++++++++++++++++++--------- + include/hw/i386/smbios.h | 4 +- + include/sysemu/arch_init.h | 2 +- + vl.c | 3 +- + 5 files changed, 179 insertions(+), 43 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + arch_init.c | 4 +- + hw/i386/smbios.c | 209 ++++++++++++++++++++++++++++++++++++-------- + include/hw/i386/smbios.h | 4 +- + include/sysemu/arch_init.h | 2 +- + vl.c | 3 +- + 5 files changed, 179 insertions(+), 43 deletions(-) + +diff --git a/arch_init.c b/arch_init.c +index 7834d36..d8c4e2e 100644 +--- a/arch_init.c ++++ b/arch_init.c +@@ -1077,10 +1077,10 @@ void do_acpitable_option(const QemuOpts *opts) + #endif + } + +-void do_smbios_option(const char *optarg) ++void do_smbios_option(QemuOpts *opts) + { + #ifdef TARGET_I386 +- smbios_entry_add(optarg); ++ smbios_entry_add(opts); + #endif + } + +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index 0608aee..abfd6f7 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -2,9 +2,11 @@ + * SMBIOS Support + * + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. ++ * Copyright (C) 2013 Red Hat, Inc. + * + * Authors: + * Alex Williamson ++ * Markus Armbruster + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. +@@ -13,6 +15,7 @@ + * GNU GPL, version 2 or (at your option) any later version. + */ + ++#include "qemu/config-file.h" + #include "qemu/error-report.h" + #include "sysemu/sysemu.h" + #include "hw/i386/smbios.h" +@@ -41,11 +44,100 @@ struct smbios_table { + #define SMBIOS_FIELD_ENTRY 0 + #define SMBIOS_TABLE_ENTRY 1 + +- + static uint8_t *smbios_entries; + static size_t smbios_entries_len; + static int smbios_type4_count = 0; + ++static QemuOptsList qemu_smbios_opts = { ++ .name = "smbios", ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head), ++ .desc = { ++ /* ++ * no elements => accept any params ++ * validation will happen later ++ */ ++ { /* end of list */ } ++ } ++}; ++ ++static const QemuOptDesc qemu_smbios_file_opts[] = { ++ { ++ .name = "file", ++ .type = QEMU_OPT_STRING, ++ .help = "binary file containing an SMBIOS element", ++ }, ++ { /* end of list */ } ++}; ++ ++static const QemuOptDesc qemu_smbios_type0_opts[] = { ++ { ++ .name = "type", ++ .type = QEMU_OPT_NUMBER, ++ .help = "SMBIOS element type", ++ },{ ++ .name = "vendor", ++ .type = QEMU_OPT_STRING, ++ .help = "vendor name", ++ },{ ++ .name = "version", ++ .type = QEMU_OPT_STRING, ++ .help = "version number", ++ },{ ++ .name = "date", ++ .type = QEMU_OPT_STRING, ++ .help = "release date", ++ },{ ++ .name = "release", ++ .type = QEMU_OPT_STRING, ++ .help = "revision number", ++ }, ++ { /* end of list */ } ++}; ++ ++static const QemuOptDesc qemu_smbios_type1_opts[] = { ++ { ++ .name = "type", ++ .type = QEMU_OPT_NUMBER, ++ .help = "SMBIOS element type", ++ },{ ++ .name = "manufacturer", ++ .type = QEMU_OPT_STRING, ++ .help = "manufacturer name", ++ },{ ++ .name = "product", ++ .type = QEMU_OPT_STRING, ++ .help = "product name", ++ },{ ++ .name = "version", ++ .type = QEMU_OPT_STRING, ++ .help = "version number", ++ },{ ++ .name = "serial", ++ .type = QEMU_OPT_STRING, ++ .help = "serial number", ++ },{ ++ .name = "uuid", ++ .type = QEMU_OPT_STRING, ++ .help = "UUID", ++ },{ ++ .name = "sku", ++ .type = QEMU_OPT_STRING, ++ .help = "SKU number", ++ },{ ++ .name = "family", ++ .type = QEMU_OPT_STRING, ++ .help = "family name", ++ }, ++ { /* end of list */ } ++}; ++ ++static void smbios_register_config(void) ++{ ++ qemu_add_opts(&qemu_smbios_opts); ++} ++ ++machine_init(smbios_register_config); ++ + static void smbios_validate_table(void) + { + if (smbios_type4_count && smbios_type4_count != smp_cpus) { +@@ -124,23 +216,30 @@ void smbios_add_field(int type, int offset, const void *data, size_t len) + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); + } + +-static void smbios_build_type_0_fields(const char *t) ++static void smbios_build_type_0_fields(QemuOpts *opts) + { +- char buf[1024]; ++ const char *val; + unsigned char major, minor; + +- if (get_param_value(buf, sizeof(buf), "vendor", t)) ++ val = qemu_opt_get(opts, "vendor"); ++ if (val) { + smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "version", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "version"); ++ if (val) { + smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "date", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "date"); ++ if (val) { + smbios_add_field(0, offsetof(struct smbios_type_0, + bios_release_date_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "release", t)) { +- if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) { ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "release"); ++ if (val) { ++ if (sscanf(val, "%hhu.%hhu", &major, &minor) != 2) { + error_report("Invalid release"); + exit(1); + } +@@ -153,47 +252,69 @@ static void smbios_build_type_0_fields(const char *t) + } + } + +-static void smbios_build_type_1_fields(const char *t) ++static void smbios_build_type_1_fields(QemuOpts *opts) + { +- char buf[1024]; ++ const char *val; + +- if (get_param_value(buf, sizeof(buf), "manufacturer", t)) ++ val = qemu_opt_get(opts, "manufacturer"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "product", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "product"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "version", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "version"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, version_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "serial", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "serial"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "uuid", t)) { +- if (qemu_uuid_parse(buf, qemu_uuid) != 0) { ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "uuid"); ++ if (val) { ++ if (qemu_uuid_parse(val, qemu_uuid) != 0) { + error_report("Invalid UUID"); + exit(1); + } + } +- if (get_param_value(buf, sizeof(buf), "sku", t)) ++ val = qemu_opt_get(opts, "sku"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str), +- buf, strlen(buf) + 1); +- if (get_param_value(buf, sizeof(buf), "family", t)) ++ val, strlen(val) + 1); ++ } ++ val = qemu_opt_get(opts, "family"); ++ if (val) { + smbios_add_field(1, offsetof(struct smbios_type_1, family_str), +- buf, strlen(buf) + 1); ++ val, strlen(val) + 1); ++ } + } + +-void smbios_entry_add(const char *t) ++void smbios_entry_add(QemuOpts *opts) + { +- char buf[1024]; ++ Error *local_err = NULL; ++ const char *val; + +- if (get_param_value(buf, sizeof(buf), "file", t)) { ++ val = qemu_opt_get(opts, "file"); ++ if (val) { + struct smbios_structure_header *header; + struct smbios_table *table; +- int size = get_image_size(buf); ++ int size; ++ ++ qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err); ++ if (local_err) { ++ error_report("%s", error_get_pretty(local_err)); ++ exit(1); ++ } + ++ size = get_image_size(val); + if (size == -1 || size < sizeof(struct smbios_structure_header)) { +- error_report("Cannot read SMBIOS file %s", buf); ++ error_report("Cannot read SMBIOS file %s", val); + exit(1); + } + +@@ -208,8 +329,8 @@ void smbios_entry_add(const char *t) + table->header.type = SMBIOS_TABLE_ENTRY; + table->header.length = cpu_to_le16(sizeof(*table) + size); + +- if (load_image(buf, table->data) != size) { +- error_report("Failed to load SMBIOS file %s", buf); ++ if (load_image(val, table->data) != size) { ++ error_report("Failed to load SMBIOS file %s", val); + exit(1); + } + +@@ -225,14 +346,26 @@ void smbios_entry_add(const char *t) + return; + } + +- if (get_param_value(buf, sizeof(buf), "type", t)) { +- unsigned long type = strtoul(buf, NULL, 0); ++ val = qemu_opt_get(opts, "type"); ++ if (val) { ++ unsigned long type = strtoul(val, NULL, 0); ++ + switch (type) { + case 0: +- smbios_build_type_0_fields(t); ++ qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err); ++ if (local_err) { ++ error_report("%s", error_get_pretty(local_err)); ++ exit(1); ++ } ++ smbios_build_type_0_fields(opts); + return; + case 1: +- smbios_build_type_1_fields(t); ++ qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err); ++ if (local_err) { ++ error_report("%s", error_get_pretty(local_err)); ++ exit(1); ++ } ++ smbios_build_type_1_fields(opts); + return; + default: + error_report("Don't know how to build fields for SMBIOS type %ld", +diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h +index 56c6108..d9f43b7 100644 +--- a/include/hw/i386/smbios.h ++++ b/include/hw/i386/smbios.h +@@ -13,7 +13,9 @@ + * + */ + +-void smbios_entry_add(const char *t); ++#include "qemu/option.h" ++ ++void smbios_entry_add(QemuOpts *opts); + void smbios_add_field(int type, int offset, const void *data, size_t len); + uint8_t *smbios_get_table(size_t *length); + +diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h +index dece913..be71bca 100644 +--- a/include/sysemu/arch_init.h ++++ b/include/sysemu/arch_init.h +@@ -28,7 +28,7 @@ extern const uint32_t arch_type; + + void select_soundhw(const char *optarg); + void do_acpitable_option(const QemuOpts *opts); +-void do_smbios_option(const char *optarg); ++void do_smbios_option(QemuOpts *opts); + void cpudef_init(void); + void audio_init(void); + int tcg_available(void); +diff --git a/vl.c b/vl.c +index b8a8cc6..e82eb1c 100644 +--- a/vl.c ++++ b/vl.c +@@ -3463,7 +3463,8 @@ int main(int argc, char **argv, char **envp) + do_acpitable_option(opts); + break; + case QEMU_OPTION_smbios: +- do_smbios_option(optarg); ++ opts = qemu_opts_parse(qemu_find_opts("smbios"), optarg, 0); ++ do_smbios_option(opts); + break; + case QEMU_OPTION_enable_kvm: + olist = qemu_find_opts("machine"); +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Decouple-system-product-from-QEMUMachine.patch b/SOURCES/kvm-smbios-Decouple-system-product-from-QEMUMachine.patch new file mode 100644 index 0000000..c61065c --- /dev/null +++ b/SOURCES/kvm-smbios-Decouple-system-product-from-QEMUMachine.patch @@ -0,0 +1,67 @@ +From fb2c8a946384ac07ad74ec3df7ee5906ffbf0b72 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:27 +0100 +Subject: [PATCH 27/29] smbios: Decouple system product from QEMUMachine + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-11-git-send-email-armbru@redhat.com> +Patchwork-id: 55247 +O-Subject: [PATCH 7.0 qemu-kvm 10/11] smbios: Decouple system product from QEMUMachine +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Michael Tsirkin doesn't trust us to keep values of QEMUMachine member +product stable in the future. Use copies instead, and in a way that +makes it obvious that they're guest ABI. + +Note that we can be trusted to keep values of member name, because +that has always been ABI. + +Signed-off-by: Markus Armbruster +(cherry picked from pending upstream submission) +--- + hw/i386/pc_piix.c | 3 ++- + hw/i386/pc_q35.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 3 ++- + hw/i386/pc_q35.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index e8fe607..396f4e4 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -116,7 +116,8 @@ static void pc_init1(QEMUMachineInitArgs *args, + } + + if (smbios_type1_defaults) { +- smbios_set_type1_defaults("QEMU", args->machine->desc, ++ /* These values are guest ABI, do not change */ ++ smbios_set_type1_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", + args->machine->name); + } + +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 3ef854a..473f01b 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -102,7 +102,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + } + + if (smbios_type1_defaults) { +- smbios_set_type1_defaults("QEMU", args->machine->desc, ++ /* These values are guest ABI, do not change */ ++ smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", + args->machine->name); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Factor-out-smbios_maybe_add_str.patch b/SOURCES/kvm-smbios-Factor-out-smbios_maybe_add_str.patch new file mode 100644 index 0000000..5e34d88 --- /dev/null +++ b/SOURCES/kvm-smbios-Factor-out-smbios_maybe_add_str.patch @@ -0,0 +1,114 @@ +From 8a7a5d92f6d6e0980e9f4119cdab88fd6e7b83e3 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 6 Nov 2013 09:11:26 +0100 +Subject: [PATCH 24/29] smbios: Factor out smbios_maybe_add_str() + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-8-git-send-email-armbru@redhat.com> +Patchwork-id: 55248 +O-Subject: [PATCH 7.0 qemu-kvm 07/11] smbios: Factor out smbios_maybe_add_str() +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit e26d3e734650640fabd7d95ace4f3a6f88725e0b) +--- + hw/i386/smbios.c | 61 +++++++++++++++++++++++--------------------------------- + 1 file changed, 25 insertions(+), 36 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/smbios.c | 61 ++++++++++++++++++++++------------------------------- + 1 files changed, 25 insertions(+), 36 deletions(-) + +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index d2dba6c..d3f1ee6 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -210,21 +210,22 @@ static void smbios_add_field(int type, int offset, const void *data, size_t len) + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); + } + +-static void smbios_build_type_0_fields(void) ++static void smbios_maybe_add_str(int type, int offset, const char *data) + { +- if (type0.vendor) { +- smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str), +- type0.vendor, strlen(type0.vendor) + 1); +- } +- if (type0.version) { +- smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str), +- type0.version, strlen(type0.version) + 1); ++ if (data) { ++ smbios_add_field(type, offset, data, strlen(data) + 1); + } +- if (type0.date) { +- smbios_add_field(0, offsetof(struct smbios_type_0, ++} ++ ++static void smbios_build_type_0_fields(void) ++{ ++ smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str), ++ type0.vendor); ++ smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str), ++ type0.version); ++ smbios_maybe_add_str(0, offsetof(struct smbios_type_0, + bios_release_date_str), +- type0.date, strlen(type0.date) + 1); +- } ++ type0.date); + if (type0.have_major_minor) { + smbios_add_field(0, offsetof(struct smbios_type_0, + system_bios_major_release), +@@ -237,30 +238,18 @@ static void smbios_build_type_0_fields(void) + + static void smbios_build_type_1_fields(void) + { +- if (type1.manufacturer) { +- smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str), +- type1.manufacturer, strlen(type1.manufacturer) + 1); +- } +- if (type1.product) { +- smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str), +- type1.product, strlen(type1.product) + 1); +- } +- if (type1.version) { +- smbios_add_field(1, offsetof(struct smbios_type_1, version_str), +- type1.version, strlen(type1.version) + 1); +- } +- if (type1.serial) { +- smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str), +- type1.serial, strlen(type1.serial) + 1); +- } +- if (type1.sku) { +- smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str), +- type1.sku, strlen(type1.sku) + 1); +- } +- if (type1.family) { +- smbios_add_field(1, offsetof(struct smbios_type_1, family_str), +- type1.family, strlen(type1.family) + 1); +- } ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str), ++ type1.manufacturer); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str), ++ type1.product); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str), ++ type1.version); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str), ++ type1.serial); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str), ++ type1.sku); ++ smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str), ++ type1.family); + if (qemu_uuid_set) { + smbios_add_field(1, offsetof(struct smbios_type_1, uuid), + qemu_uuid, 16); +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Improve-diagnostics-for-conflicting-entries.patch b/SOURCES/kvm-smbios-Improve-diagnostics-for-conflicting-entries.patch new file mode 100644 index 0000000..0518612 --- /dev/null +++ b/SOURCES/kvm-smbios-Improve-diagnostics-for-conflicting-entries.patch @@ -0,0 +1,113 @@ +From 3a4932455a7f7926b673089170f55de437eec5fa Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:22 +0100 +Subject: [PATCH 22/29] smbios: Improve diagnostics for conflicting entries + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-6-git-send-email-armbru@redhat.com> +Patchwork-id: 55243 +O-Subject: [PATCH 7.0 qemu-kvm 05/11] smbios: Improve diagnostics for conflicting entries +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +We allow either tables or fields for the same type. Makes sense, +because SeaBIOS uses fields only when no tables are present. + +We do this by searching the SMBIOS blob for a previously added table +or field. Error messages look like this: + + qemu-system-x86_64: -smbios type=1,serial=42: SMBIOS type 1 table already defined, cannot add field + +User needs to know that "table" is defined by -smbios file=..., and +"field" by -smbios type=... + +Instead of searching the blob, record additions of interest, and check +that. Simpler, and makes better error messages possible: + + qemu-system-x86_64: -smbios file=smbios_type_1.bin: Can't mix file= and type= for same type + qemu-system-x86_64: -smbios type=1,serial=42,serial=99: This is the conflicting setting + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit ec2df8c10a4585ba4641ae482cf2f5f13daa810e) +--- + hw/i386/smbios.c | 43 +++++++++++++++++-------------------------- + 1 file changed, 17 insertions(+), 26 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/smbios.c | 43 +++++++++++++++++-------------------------- + 1 files changed, 17 insertions(+), 26 deletions(-) + +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index abfd6f7..4263551 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -48,6 +48,12 @@ static uint8_t *smbios_entries; + static size_t smbios_entries_len; + static int smbios_type4_count = 0; + ++static struct { ++ bool seen; ++ int headertype; ++ Location loc; ++} first_opt[2]; ++ + static QemuOptsList qemu_smbios_opts = { + .name = "smbios", + .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head), +@@ -159,35 +165,20 @@ uint8_t *smbios_get_table(size_t *length) + */ + static void smbios_check_collision(int type, int entry) + { +- uint16_t *num_entries = (uint16_t *)smbios_entries; +- struct smbios_header *header; +- char *p; +- int i; +- +- if (!num_entries) +- return; +- +- p = (char *)(num_entries + 1); +- +- for (i = 0; i < *num_entries; i++) { +- header = (struct smbios_header *)p; +- if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) { +- struct smbios_field *field = (void *)header; +- if (type == field->type) { +- error_report("SMBIOS type %d field already defined, " +- "cannot add table", type); +- exit(1); +- } +- } else if (entry == SMBIOS_FIELD_ENTRY && +- header->type == SMBIOS_TABLE_ENTRY) { +- struct smbios_structure_header *table = (void *)(header + 1); +- if (type == table->type) { +- error_report("SMBIOS type %d table already defined, " +- "cannot add field", type); ++ if (type < ARRAY_SIZE(first_opt)) { ++ if (first_opt[type].seen) { ++ if (first_opt[type].headertype != entry) { ++ error_report("Can't mix file= and type= for same type"); ++ loc_push_restore(&first_opt[type].loc); ++ error_report("This is the conflicting setting"); ++ loc_pop(&first_opt[type].loc); + exit(1); + } ++ } else { ++ first_opt[type].seen = true; ++ first_opt[type].headertype = entry; ++ loc_save(&first_opt[type].loc); + } +- p += le16_to_cpu(header->length); + } + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Make-multiple-smbios-type-accumulate-sanely.patch b/SOURCES/kvm-smbios-Make-multiple-smbios-type-accumulate-sanely.patch new file mode 100644 index 0000000..a990243 --- /dev/null +++ b/SOURCES/kvm-smbios-Make-multiple-smbios-type-accumulate-sanely.patch @@ -0,0 +1,361 @@ +From f602774bca68ddc853f88cf90c62e1af94390731 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Wed, 6 Nov 2013 09:09:09 +0100 +Subject: [PATCH 23/29] smbios: Make multiple -smbios type= accumulate sanely + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-7-git-send-email-armbru@redhat.com> +Patchwork-id: 55244 +O-Subject: [PATCH 7.0 qemu-kvm 06/11] smbios: Make multiple -smbios type= accumulate sanely +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Currently, -smbios type=T,NAME=VAL,... adds one field (T,NAME) with +value VAL to fw_cfg for each unique NAME. If NAME occurs multiple +times, the last one's VAL is used (before the QemuOpts conversion, the +first one was used). + +Multiple -smbios can add multiple fields with the same (T, NAME). +SeaBIOS reads all of them from fw_cfg, but uses only the first field +(T, NAME). The others are ignored. + +"First one wins, subsequent ones get ignored silently" isn't nice. We +commonly let the last option win. Useful, because it lets you +-readconfig first, then selectively override with command line +options. + +Clean up -smbios to work the common way. Accumulate the settings, +with later ones overwriting earlier ones. Put the result into fw_cfg +(no more useless duplicates). + +Bonus cleanup: qemu_uuid_parse() no longer sets SMBIOS system uuid by +side effect. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit fc3b32958a80bca13309e2695de07b43dd788421) + +Signed-off-by: Miroslav Rezanina +--- + arch_init.c | 3 - + hw/i386/smbios.c | 152 +++++++++++++++++++++++++++------------------ + include/hw/i386/smbios.h | 1 - + include/sysemu/sysemu.h | 1 + + vl.c | 2 + + 5 files changed, 94 insertions(+), 65 deletions(-) + +diff --git a/arch_init.c b/arch_init.c +index d8c4e2e..5301cfd 100644 +--- a/arch_init.c ++++ b/arch_init.c +@@ -1056,9 +1056,6 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid) + if (ret != 16) { + return -1; + } +-#ifdef TARGET_I386 +- smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16); +-#endif + return 0; + } + +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index 4263551..d2dba6c 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -47,6 +47,7 @@ struct smbios_table { + static uint8_t *smbios_entries; + static size_t smbios_entries_len; + static int smbios_type4_count = 0; ++static bool smbios_immutable; + + static struct { + bool seen; +@@ -54,6 +55,17 @@ static struct { + Location loc; + } first_opt[2]; + ++static struct { ++ const char *vendor, *version, *date; ++ bool have_major_minor; ++ uint8_t major, minor; ++} type0; ++ ++static struct { ++ const char *manufacturer, *product, *version, *serial, *sku, *family; ++ /* uuid is in qemu_uuid[] */ ++} type1; ++ + static QemuOptsList qemu_smbios_opts = { + .name = "smbios", + .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head), +@@ -152,13 +164,6 @@ static void smbios_validate_table(void) + } + } + +-uint8_t *smbios_get_table(size_t *length) +-{ +- smbios_validate_table(); +- *length = smbios_entries_len; +- return smbios_entries; +-} +- + /* + * To avoid unresolvable overlaps in data, don't allow both + * tables and fields for the same smbios type. +@@ -182,12 +187,10 @@ static void smbios_check_collision(int type, int entry) + } + } + +-void smbios_add_field(int type, int offset, const void *data, size_t len) ++static void smbios_add_field(int type, int offset, const void *data, size_t len) + { + struct smbios_field *field; + +- smbios_check_collision(type, SMBIOS_FIELD_ENTRY); +- + if (!smbios_entries) { + smbios_entries_len = sizeof(uint16_t); + smbios_entries = g_malloc0(smbios_entries_len); +@@ -207,82 +210,81 @@ void smbios_add_field(int type, int offset, const void *data, size_t len) + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); + } + +-static void smbios_build_type_0_fields(QemuOpts *opts) ++static void smbios_build_type_0_fields(void) + { +- const char *val; +- unsigned char major, minor; +- +- val = qemu_opt_get(opts, "vendor"); +- if (val) { ++ if (type0.vendor) { + smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str), +- val, strlen(val) + 1); ++ type0.vendor, strlen(type0.vendor) + 1); + } +- val = qemu_opt_get(opts, "version"); +- if (val) { ++ if (type0.version) { + smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str), +- val, strlen(val) + 1); ++ type0.version, strlen(type0.version) + 1); + } +- val = qemu_opt_get(opts, "date"); +- if (val) { ++ if (type0.date) { + smbios_add_field(0, offsetof(struct smbios_type_0, + bios_release_date_str), +- val, strlen(val) + 1); ++ type0.date, strlen(type0.date) + 1); + } +- val = qemu_opt_get(opts, "release"); +- if (val) { +- if (sscanf(val, "%hhu.%hhu", &major, &minor) != 2) { +- error_report("Invalid release"); +- exit(1); +- } ++ if (type0.have_major_minor) { + smbios_add_field(0, offsetof(struct smbios_type_0, + system_bios_major_release), +- &major, 1); ++ &type0.major, 1); + smbios_add_field(0, offsetof(struct smbios_type_0, + system_bios_minor_release), +- &minor, 1); ++ &type0.minor, 1); + } + } + +-static void smbios_build_type_1_fields(QemuOpts *opts) ++static void smbios_build_type_1_fields(void) + { +- const char *val; +- +- val = qemu_opt_get(opts, "manufacturer"); +- if (val) { ++ if (type1.manufacturer) { + smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str), +- val, strlen(val) + 1); ++ type1.manufacturer, strlen(type1.manufacturer) + 1); + } +- val = qemu_opt_get(opts, "product"); +- if (val) { ++ if (type1.product) { + smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str), +- val, strlen(val) + 1); ++ type1.product, strlen(type1.product) + 1); + } +- val = qemu_opt_get(opts, "version"); +- if (val) { ++ if (type1.version) { + smbios_add_field(1, offsetof(struct smbios_type_1, version_str), +- val, strlen(val) + 1); ++ type1.version, strlen(type1.version) + 1); + } +- val = qemu_opt_get(opts, "serial"); +- if (val) { ++ if (type1.serial) { + smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str), +- val, strlen(val) + 1); +- } +- val = qemu_opt_get(opts, "uuid"); +- if (val) { +- if (qemu_uuid_parse(val, qemu_uuid) != 0) { +- error_report("Invalid UUID"); +- exit(1); +- } ++ type1.serial, strlen(type1.serial) + 1); + } +- val = qemu_opt_get(opts, "sku"); +- if (val) { ++ if (type1.sku) { + smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str), +- val, strlen(val) + 1); ++ type1.sku, strlen(type1.sku) + 1); + } +- val = qemu_opt_get(opts, "family"); +- if (val) { ++ if (type1.family) { + smbios_add_field(1, offsetof(struct smbios_type_1, family_str), +- val, strlen(val) + 1); ++ type1.family, strlen(type1.family) + 1); ++ } ++ if (qemu_uuid_set) { ++ smbios_add_field(1, offsetof(struct smbios_type_1, uuid), ++ qemu_uuid, 16); ++ } ++} ++ ++uint8_t *smbios_get_table(size_t *length) ++{ ++ if (!smbios_immutable) { ++ smbios_build_type_0_fields(); ++ smbios_build_type_1_fields(); ++ smbios_validate_table(); ++ smbios_immutable = true; ++ } ++ *length = smbios_entries_len; ++ return smbios_entries; ++} ++ ++static void save_opt(const char **dest, QemuOpts *opts, const char *name) ++{ ++ const char *val = qemu_opt_get(opts, name); ++ ++ if (val) { ++ *dest = val; + } + } + +@@ -291,6 +293,7 @@ void smbios_entry_add(QemuOpts *opts) + Error *local_err = NULL; + const char *val; + ++ assert(!smbios_immutable); + val = qemu_opt_get(opts, "file"); + if (val) { + struct smbios_structure_header *header; +@@ -341,6 +344,8 @@ void smbios_entry_add(QemuOpts *opts) + if (val) { + unsigned long type = strtoul(val, NULL, 0); + ++ smbios_check_collision(type, SMBIOS_FIELD_ENTRY); ++ + switch (type) { + case 0: + qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err); +@@ -348,7 +353,18 @@ void smbios_entry_add(QemuOpts *opts) + error_report("%s", error_get_pretty(local_err)); + exit(1); + } +- smbios_build_type_0_fields(opts); ++ save_opt(&type0.vendor, opts, "vendor"); ++ save_opt(&type0.version, opts, "version"); ++ save_opt(&type0.date, opts, "date"); ++ ++ val = qemu_opt_get(opts, "release"); ++ if (val) { ++ if (sscanf(val, "%hhu.%hhu", &type0.major, &type0.minor) != 2) { ++ error_report("Invalid release"); ++ exit(1); ++ } ++ type0.have_major_minor = true; ++ } + return; + case 1: + qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err); +@@ -356,7 +372,21 @@ void smbios_entry_add(QemuOpts *opts) + error_report("%s", error_get_pretty(local_err)); + exit(1); + } +- smbios_build_type_1_fields(opts); ++ save_opt(&type1.manufacturer, opts, "manufacturer"); ++ save_opt(&type1.product, opts, "product"); ++ save_opt(&type1.version, opts, "version"); ++ save_opt(&type1.serial, opts, "serial"); ++ save_opt(&type1.sku, opts, "sku"); ++ save_opt(&type1.family, opts, "family"); ++ ++ val = qemu_opt_get(opts, "uuid"); ++ if (val) { ++ if (qemu_uuid_parse(val, qemu_uuid) != 0) { ++ error_report("Invalid UUID"); ++ exit(1); ++ } ++ qemu_uuid_set = true; ++ } + return; + default: + error_report("Don't know how to build fields for SMBIOS type %ld", +diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h +index d9f43b7..b08ec71 100644 +--- a/include/hw/i386/smbios.h ++++ b/include/hw/i386/smbios.h +@@ -16,7 +16,6 @@ + #include "qemu/option.h" + + void smbios_entry_add(QemuOpts *opts); +-void smbios_add_field(int type, int offset, const void *data, size_t len); + uint8_t *smbios_get_table(size_t *length); + + /* +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index 76c5b64..8fbc818 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -16,6 +16,7 @@ extern const char *bios_name; + + extern const char *qemu_name; + extern uint8_t qemu_uuid[]; ++extern bool qemu_uuid_set; + int qemu_uuid_parse(const char *str, uint8_t *uuid); + + #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" +diff --git a/vl.c b/vl.c +index e82eb1c..19cc3b2 100644 +--- a/vl.c ++++ b/vl.c +@@ -256,6 +256,7 @@ uint64_t node_mem[MAX_NODES]; + unsigned long *node_cpumask[MAX_NODES]; + + uint8_t qemu_uuid[16]; ++bool qemu_uuid_set; + + static QEMUBootSetHandler *boot_set_handler; + static void *boot_set_opaque; +@@ -3573,6 +3574,7 @@ int main(int argc, char **argv, char **envp) + " Wrong format.\n"); + exit(1); + } ++ qemu_uuid_set = true; + break; + case QEMU_OPTION_option_rom: + if (nb_option_roms >= MAX_OPTION_ROMS) { +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Normalize-smbios_entry_add-s-error-handling-t.patch b/SOURCES/kvm-smbios-Normalize-smbios_entry_add-s-error-handling-t.patch new file mode 100644 index 0000000..e7c5061 --- /dev/null +++ b/SOURCES/kvm-smbios-Normalize-smbios_entry_add-s-error-handling-t.patch @@ -0,0 +1,109 @@ +From d2bfd3e4bb4a6115dc40b56e885a68887df30f94 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:20 +0100 +Subject: [PATCH 20/29] smbios: Normalize smbios_entry_add()'s error handling to exit(1) + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-4-git-send-email-armbru@redhat.com> +Patchwork-id: 55241 +O-Subject: [PATCH 7.0 qemu-kvm 03/11] smbios: Normalize smbios_entry_add()'s error handling to exit(1) +Bugzilla: 994490 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +It exits on all error conditions but one, where it returns -1. +Normalize, and return void. + +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 351a6a73ca7a9123f0dfd6c6f85fd01e82fe3741) +--- + arch_init.c | 4 +--- + hw/i386/smbios.c | 10 +++++----- + include/hw/i386/smbios.h | 2 +- + 3 files changed, 7 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + arch_init.c | 4 +--- + hw/i386/smbios.c | 10 +++++----- + include/hw/i386/smbios.h | 2 +- + 3 files changed, 7 insertions(+), 9 deletions(-) + +diff --git a/arch_init.c b/arch_init.c +index cd2bb5a..7834d36 100644 +--- a/arch_init.c ++++ b/arch_init.c +@@ -1080,9 +1080,7 @@ void do_acpitable_option(const QemuOpts *opts) + void do_smbios_option(const char *optarg) + { + #ifdef TARGET_I386 +- if (smbios_entry_add(optarg) < 0) { +- exit(1); +- } ++ smbios_entry_add(optarg); + #endif + } + +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index e708cb8..0608aee 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -183,7 +183,7 @@ static void smbios_build_type_1_fields(const char *t) + buf, strlen(buf) + 1); + } + +-int smbios_entry_add(const char *t) ++void smbios_entry_add(const char *t) + { + char buf[1024]; + +@@ -222,7 +222,7 @@ int smbios_entry_add(const char *t) + smbios_entries_len += sizeof(*table) + size; + (*(uint16_t *)smbios_entries) = + cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1); +- return 0; ++ return; + } + + if (get_param_value(buf, sizeof(buf), "type", t)) { +@@ -230,10 +230,10 @@ int smbios_entry_add(const char *t) + switch (type) { + case 0: + smbios_build_type_0_fields(t); +- return 0; ++ return; + case 1: + smbios_build_type_1_fields(t); +- return 0; ++ return; + default: + error_report("Don't know how to build fields for SMBIOS type %ld", + type); +@@ -242,5 +242,5 @@ int smbios_entry_add(const char *t) + } + + error_report("Must specify type= or file="); +- return -1; ++ exit(1); + } +diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h +index 9babeaf..56c6108 100644 +--- a/include/hw/i386/smbios.h ++++ b/include/hw/i386/smbios.h +@@ -13,7 +13,7 @@ + * + */ + +-int smbios_entry_add(const char *t); ++void smbios_entry_add(const char *t); + void smbios_add_field(int type, int offset, const void *data, size_t len); + uint8_t *smbios_get_table(size_t *length); + +-- +1.7.1 + diff --git a/SOURCES/kvm-smbios-Set-system-manufacturer-product-version-by-de.patch b/SOURCES/kvm-smbios-Set-system-manufacturer-product-version-by-de.patch new file mode 100644 index 0000000..095223e --- /dev/null +++ b/SOURCES/kvm-smbios-Set-system-manufacturer-product-version-by-de.patch @@ -0,0 +1,149 @@ +From 1123ee2cf18b526b19fc3770f20c91b1ac409cf7 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Sat, 2 Nov 2013 10:01:26 +0100 +Subject: [PATCH 26/29] smbios: Set system manufacturer, product & version by default + +RH-Author: Markus Armbruster +Message-id: <1383386488-29789-10-git-send-email-armbru@redhat.com> +Patchwork-id: 55245 +O-Subject: [PATCH 7.0 qemu-kvm 09/11] smbios: Set system manufacturer, product & version by default +Bugzilla: 994490 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +Currently, we get SeaBIOS defaults: manufacturer Bochs, product Bochs, +no version. Best SeaBIOS can do, but we can provide better defaults: +manufacturer QEMU, product & version taken from QEMUMachine desc and +name. + +Take care to do this only for new machine types, of course. + +Signed-off-by: Markus Armbruster +(cherry picked from pending upstream submission) + +Conflicts: + hw/i386/pc_piix.c + hw/i386/pc_q35.c +--- + hw/i386/pc_piix.c | 7 +++++++ + hw/i386/pc_q35.c | 7 +++++++ + hw/i386/smbios.c | 14 ++++++++++++++ + include/hw/i386/smbios.h | 2 ++ + 4 files changed, 30 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/i386/pc_piix.c | 7 +++++++ + hw/i386/pc_q35.c | 7 +++++++ + hw/i386/smbios.c | 14 ++++++++++++++ + include/hw/i386/smbios.h | 2 ++ + 4 files changed, 30 insertions(+), 0 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 65f7f3a..e8fe607 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -27,6 +27,7 @@ + #include "hw/hw.h" + #include "hw/i386/pc.h" + #include "hw/i386/apic.h" ++#include "hw/i386/smbios.h" + #include "hw/pci/pci.h" + #include "hw/pci/pci_ids.h" + #include "hw/usb.h" +@@ -57,6 +58,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; + static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; + + static bool has_pvpanic = true; ++static bool smbios_type1_defaults = true; + + /* PC hardware initialisation */ + static void pc_init1(QEMUMachineInitArgs *args, +@@ -113,6 +115,11 @@ static void pc_init1(QEMUMachineInitArgs *args, + rom_memory = system_memory; + } + ++ if (smbios_type1_defaults) { ++ smbios_set_type1_defaults("QEMU", args->machine->desc, ++ args->machine->name); ++ } ++ + /* allocate ram and load rom/bios */ + if (!xen_enabled()) { + fw_cfg = pc_memory_init(system_memory, +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 99d3a10..3ef854a 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -38,6 +38,7 @@ + #include "hw/pci-host/q35.h" + #include "exec/address-spaces.h" + #include "hw/i386/ich9.h" ++#include "hw/i386/smbios.h" + #include "hw/ide/pci.h" + #include "hw/ide/ahci.h" + #include "hw/usb.h" +@@ -47,6 +48,7 @@ + #define MAX_SATA_PORTS 6 + + static bool has_pvpanic = true; ++static bool smbios_type1_defaults = true; + + /* PC hardware initialisation */ + static void pc_q35_init(QEMUMachineInitArgs *args) +@@ -99,6 +101,11 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + rom_memory = get_system_memory(); + } + ++ if (smbios_type1_defaults) { ++ smbios_set_type1_defaults("QEMU", args->machine->desc, ++ args->machine->name); ++ } ++ + /* allocate ram and load rom/bios */ + if (!xen_enabled()) { + pc_memory_init(get_system_memory(), +diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c +index d3f1ee6..e8f41ad 100644 +--- a/hw/i386/smbios.c ++++ b/hw/i386/smbios.c +@@ -256,6 +256,20 @@ static void smbios_build_type_1_fields(void) + } + } + ++void smbios_set_type1_defaults(const char *manufacturer, ++ const char *product, const char *version) ++{ ++ if (!type1.manufacturer) { ++ type1.manufacturer = manufacturer; ++ } ++ if (!type1.product) { ++ type1.product = product; ++ } ++ if (!type1.version) { ++ type1.version = version; ++ } ++} ++ + uint8_t *smbios_get_table(size_t *length) + { + if (!smbios_immutable) { +diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h +index b08ec71..18fb970 100644 +--- a/include/hw/i386/smbios.h ++++ b/include/hw/i386/smbios.h +@@ -16,6 +16,8 @@ + #include "qemu/option.h" + + void smbios_entry_add(QemuOpts *opts); ++void smbios_set_type1_defaults(const char *manufacturer, ++ const char *product, const char *version); + uint8_t *smbios_get_table(size_t *length); + + /* +-- +1.7.1 + diff --git a/SOURCES/kvm-spice-fix-display-initialization.patch b/SOURCES/kvm-spice-fix-display-initialization.patch new file mode 100644 index 0000000..ead65b8 --- /dev/null +++ b/SOURCES/kvm-spice-fix-display-initialization.patch @@ -0,0 +1,113 @@ +From e2022d7c9e8623092daeca9c9a3f6118f3c7239e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Fri, 30 Aug 2013 07:08:09 +0200 +Subject: [PATCH 01/29] spice: fix display initialization + +RH-Author: Gerd Hoffmann +Message-id: <1377846489-22691-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 53931 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] spice: fix display initialization +Bugzilla: 974887 +RH-Acked-by: Hans de Goede +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Markus Armbruster + +Spice has two display interface implementations: One integrated into +the qxl graphics card, and one generic which can operate with every +qemu-emulated graphics card. + +The generic one is activated in case spice is used without qxl. The +logic for that only caught the "-vga qxl" case, "-device qxl-vga" goes +unnoticed. Fix that by adding a check in the spice interface +registration so we'll notice the qxl card no matter how it is created. + +https://bugzilla.redhat.com/show_bug.cgi?id=981094 + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 58ae52a8dc7752e3da9a905678580b4cb8181cdc) +--- + include/sysemu/sysemu.h | 1 - + include/ui/qemu-spice.h | 2 ++ + ui/spice-core.c | 5 +++++ + vl.c | 2 +- + 4 files changed, 8 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + include/sysemu/sysemu.h | 1 - + include/ui/qemu-spice.h | 2 ++ + ui/spice-core.c | 5 +++++ + vl.c | 2 +- + 4 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index 3caeb66..d7a77b6 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -103,7 +103,6 @@ typedef enum { + + extern int vga_interface_type; + #define xenfb_enabled (vga_interface_type == VGA_XENFB) +-#define qxl_enabled (vga_interface_type == VGA_QXL) + + extern int graphic_width; + extern int graphic_height; +diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h +index eba6d77..c6c756b 100644 +--- a/include/ui/qemu-spice.h ++++ b/include/ui/qemu-spice.h +@@ -27,6 +27,7 @@ + #include "monitor/monitor.h" + + extern int using_spice; ++extern int spice_displays; + + void qemu_spice_init(void); + void qemu_spice_input_init(void); +@@ -57,6 +58,7 @@ static inline CharDriverState *qemu_chr_open_spice_port(const char *name) + #include "monitor/monitor.h" + + #define using_spice 0 ++#define spice_displays 0 + static inline int qemu_spice_set_passwd(const char *passwd, + bool fail_if_connected, + bool disconnect_if_connected) +diff --git a/ui/spice-core.c b/ui/spice-core.c +index bcc4199..c8337ab 100644 +--- a/ui/spice-core.c ++++ b/ui/spice-core.c +@@ -48,6 +48,7 @@ static char *auth_passwd; + static time_t auth_expires = TIME_MAX; + static int spice_migration_completed; + int using_spice = 0; ++int spice_displays; + + static QemuThread me; + +@@ -823,6 +824,10 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin) + qemu_add_vm_change_state_handler(vm_change_state_handler, NULL); + } + ++ if (strcmp(sin->sif->type, SPICE_INTERFACE_QXL) == 0) { ++ spice_displays++; ++ } ++ + return spice_server_add_interface(spice_server, sin); + } + +diff --git a/vl.c b/vl.c +index 51c04e7..f7b326a 100644 +--- a/vl.c ++++ b/vl.c +@@ -4405,7 +4405,7 @@ int main(int argc, char **argv, char **envp) + } + #endif + #ifdef CONFIG_SPICE +- if (using_spice && !qxl_enabled) { ++ if (using_spice && !spice_displays) { + qemu_spice_display_init(ds); + } + #endif +-- +1.7.1 + diff --git a/SOURCES/kvm-sysbus-Set-cannot_instantiate_with_device_add_yet.patch b/SOURCES/kvm-sysbus-Set-cannot_instantiate_with_device_add_yet.patch new file mode 100644 index 0000000..d1f05ce --- /dev/null +++ b/SOURCES/kvm-sysbus-Set-cannot_instantiate_with_device_add_yet.patch @@ -0,0 +1,499 @@ +From a44e7ab97ff7ed0494ba8746c73aa66afa506ef4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:13 +0100 +Subject: [PATCH 37/81] sysbus: Set cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-9-git-send-email-kwolf@redhat.com> +Patchwork-id: 55534 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 08/17] sysbus: Set cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +device_add plugs devices into suitable bus. For "real" buses, that +actually connects the device. For sysbus, the connections need to be +made separately, and device_add can't do that. The device would be +left unconnected, and could not possibly work. + +Quite a few, but not all sysbus devices already set +cannot_instantiate_with_device_add_yet in their class init function. + +Set it in their abstract base's class init function +sysbus_device_class_init(), and remove the now redundant assignments +from device class init functions. + +Signed-off-by: Markus Armbruster +Reviewed-by: Marcel Apfelbaum +(cherry picked from pending upstream submission) + +Conflicts: + hw/dma/pl080.c + hw/i386/kvm/clock.c + hw/nvram/fw_cfg.c + hw/pci-host/piix.c + hw/timer/hpet.c + +Conflict resolution is always the same: drop redundant assignment, +keep context intact. Three additional redundant assignments dropped +in hw/display/pl110.c and hw/dma/pl080.c. +Signed-off-by: Kevin Wolf +--- + hw/alpha/typhoon.c | 2 -- + hw/arm/versatilepb.c | 1 - + hw/audio/pl041.c | 1 - + hw/core/sysbus.c | 7 +++++++ + hw/display/pl110.c | 3 --- + hw/dma/pl080.c | 2 -- + hw/i386/kvm/clock.c | 1 - + hw/i386/kvmvapic.c | 1 - + hw/intc/arm_gic.c | 1 - + hw/intc/arm_gic_common.c | 1 - + hw/intc/arm_gic_kvm.c | 1 - + hw/intc/ioapic_common.c | 1 - + hw/intc/pl190.c | 1 - + hw/isa/isa-bus.c | 1 - + hw/misc/arm_l2x0.c | 1 - + hw/nvram/fw_cfg.c | 1 - + hw/pci-host/bonito.c | 2 -- + hw/pci-host/grackle.c | 2 -- + hw/pci-host/piix.c | 1 - + hw/pci-host/prep.c | 1 - + hw/ppc/spapr_vio.c | 2 -- + hw/s390x/ipl.c | 1 - + hw/s390x/s390-virtio-bus.c | 2 -- + hw/s390x/virtio-ccw.c | 2 -- + hw/sd/pl181.c | 1 - + hw/timer/arm_mptimer.c | 1 - + hw/timer/hpet.c | 1 - + hw/timer/pl031.c | 1 - + 28 files changed, 7 insertions(+), 36 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/alpha/typhoon.c | 2 -- + hw/arm/versatilepb.c | 1 - + hw/audio/pl041.c | 1 - + hw/core/sysbus.c | 7 +++++++ + hw/display/pl110.c | 3 --- + hw/dma/pl080.c | 2 -- + hw/i386/kvm/clock.c | 1 - + hw/i386/kvmvapic.c | 1 - + hw/intc/arm_gic.c | 1 - + hw/intc/arm_gic_common.c | 1 - + hw/intc/arm_gic_kvm.c | 1 - + hw/intc/ioapic_common.c | 1 - + hw/intc/pl190.c | 1 - + hw/isa/isa-bus.c | 1 - + hw/misc/arm_l2x0.c | 1 - + hw/nvram/fw_cfg.c | 1 - + hw/pci-host/bonito.c | 2 -- + hw/pci-host/grackle.c | 2 -- + hw/pci-host/piix.c | 1 - + hw/pci-host/prep.c | 1 - + hw/ppc/spapr_vio.c | 2 -- + hw/s390x/ipl.c | 1 - + hw/s390x/s390-virtio-bus.c | 2 -- + hw/s390x/virtio-ccw.c | 2 -- + hw/sd/pl181.c | 1 - + hw/timer/arm_mptimer.c | 1 - + hw/timer/hpet.c | 1 - + hw/timer/pl031.c | 1 - + 28 files changed, 7 insertions(+), 36 deletions(-) + +diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c +index 55a0e76..070c34b 100644 +--- a/hw/alpha/typhoon.c ++++ b/hw/alpha/typhoon.c +@@ -819,11 +819,9 @@ static int typhoon_pcihost_init(SysBusDevice *dev) + + static void typhoon_pcihost_class_init(ObjectClass *klass, void *data) + { +- DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = typhoon_pcihost_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo typhoon_pcihost_info = { +diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c +index 84cd1ed..adc7a5d 100644 +--- a/hw/arm/versatilepb.c ++++ b/hw/arm/versatilepb.c +@@ -387,7 +387,6 @@ static void vpb_sic_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = vpb_sic_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_vpb_sic; + } + +diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c +index 36a7ecb..227ddf9 100644 +--- a/hw/audio/pl041.c ++++ b/hw/audio/pl041.c +@@ -627,7 +627,6 @@ static void pl041_device_class_init(ObjectClass *klass, void *data) + + k->init = pl041_init; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = pl041_device_reset; + dc->vmsd = &vmstate_pl041; + dc->props = pl041_device_properties; +diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c +index 9004d8c..e07f1c4 100644 +--- a/hw/core/sysbus.c ++++ b/hw/core/sysbus.c +@@ -257,6 +257,13 @@ static void sysbus_device_class_init(ObjectClass *klass, void *data) + DeviceClass *k = DEVICE_CLASS(klass); + k->init = sysbus_device_init; + k->bus_type = TYPE_SYSTEM_BUS; ++ /* ++ * device_add plugs devices into suitable bus. For "real" buses, ++ * that actually connects the device. For sysbus, the connections ++ * need to be made separately, and device_add can't do that. The ++ * device would be left unconncected, and could not possibly work. ++ */ ++ k->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo sysbus_device_type_info = { +diff --git a/hw/display/pl110.c b/hw/display/pl110.c +index 173ddf8..f4acf78 100644 +--- a/hw/display/pl110.c ++++ b/hw/display/pl110.c +@@ -482,7 +482,6 @@ static void pl110_class_init(ObjectClass *klass, void *data) + + k->init = pl110_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +@@ -500,7 +499,6 @@ static void pl110_versatile_class_init(ObjectClass *klass, void *data) + + k->init = pl110_versatile_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +@@ -518,7 +516,6 @@ static void pl111_class_init(ObjectClass *klass, void *data) + + k->init = pl111_init; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl110; + } + +diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c +index 2920780..e00ccdb 100644 +--- a/hw/dma/pl080.c ++++ b/hw/dma/pl080.c +@@ -382,7 +382,6 @@ static void pl080_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl080_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl080; + } + +@@ -399,7 +398,6 @@ static void pl081_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl081_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl080; + } + +diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c +index 6204939..6d6f3a7 100644 +--- a/hw/i386/kvm/clock.c ++++ b/hw/i386/kvm/clock.c +@@ -110,7 +110,6 @@ static void kvmclock_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = kvmclock_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &kvmclock_vmsd; + } + +diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c +index e6405da..a7db94d 100644 +--- a/hw/i386/kvmvapic.c ++++ b/hw/i386/kvmvapic.c +@@ -809,7 +809,6 @@ static void vapic_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = vapic_reset; + dc->vmsd = &vmstate_vapic; + sc->init = vapic_init; +diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c +index 243cbf1..8c72437 100644 +--- a/hw/intc/arm_gic.c ++++ b/hw/intc/arm_gic.c +@@ -702,7 +702,6 @@ static void arm_gic_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + ARMGICClass *agc = ARM_GIC_CLASS(klass); + +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + agc->parent_realize = dc->realize; + dc->realize = arm_gic_realize; + } +diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c +index 26b7756..0192537 100644 +--- a/hw/intc/arm_gic_common.c ++++ b/hw/intc/arm_gic_common.c +@@ -156,7 +156,6 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data) + dc->realize = arm_gic_common_realize; + dc->props = arm_gic_common_properties; + dc->vmsd = &vmstate_gic; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo arm_gic_common_type = { +diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c +index cb4ce23..9b8a106 100644 +--- a/hw/intc/arm_gic_kvm.c ++++ b/hw/intc/arm_gic_kvm.c +@@ -148,7 +148,6 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data) + kgc->parent_reset = dc->reset; + dc->realize = kvm_arm_gic_realize; + dc->reset = kvm_arm_gic_reset; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo kvm_arm_gic_info = { +diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c +index ce610b7..8e555de 100644 +--- a/hw/intc/ioapic_common.c ++++ b/hw/intc/ioapic_common.c +@@ -100,7 +100,6 @@ static void ioapic_common_class_init(ObjectClass *klass, void *data) + + sc->init = ioapic_init_common; + dc->vmsd = &vmstate_ioapic_common; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo ioapic_common_type = { +diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c +index ff0e5b0..2cda150 100644 +--- a/hw/intc/pl190.c ++++ b/hw/intc/pl190.c +@@ -269,7 +269,6 @@ static void pl190_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl190_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = pl190_reset; + dc->vmsd = &vmstate_pl190; + } +diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c +index a87a841..3471d0f 100644 +--- a/hw/isa/isa-bus.c ++++ b/hw/isa/isa-bus.c +@@ -217,7 +217,6 @@ static void isabus_bridge_class_init(ObjectClass *klass, void *data) + + k->init = isabus_bridge_init; + dc->fw_name = "isa"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo isabus_bridge_info = { +diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c +index 2b19e34..21bf291 100644 +--- a/hw/misc/arm_l2x0.c ++++ b/hw/misc/arm_l2x0.c +@@ -174,7 +174,6 @@ static void l2x0_class_init(ObjectClass *klass, void *data) + + k->init = l2x0_priv_init; + dc->vmsd = &vmstate_l2x0; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = l2x0_properties; + dc->reset = l2x0_priv_reset; + } +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 155edd4..3fa1488 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -559,7 +559,6 @@ static void fw_cfg_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = fw_cfg_init1; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = fw_cfg_reset; + dc->vmsd = &vmstate_fw_cfg; + dc->props = fw_cfg_properties; +diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c +index b73359e..c2a056a 100644 +--- a/hw/pci-host/bonito.c ++++ b/hw/pci-host/bonito.c +@@ -824,11 +824,9 @@ static const TypeInfo bonito_info = { + + static void bonito_pcihost_class_init(ObjectClass *klass, void *data) + { +- DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = bonito_pcihost_initfn; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo bonito_pcihost_info = { +diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c +index 5eb2840..4643beb 100644 +--- a/hw/pci-host/grackle.c ++++ b/hw/pci-host/grackle.c +@@ -143,10 +143,8 @@ static const TypeInfo grackle_pci_info = { + static void pci_grackle_class_init(ObjectClass *klass, void *data) + { + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); +- DeviceClass *dc = DEVICE_CLASS(klass); + + k->init = pci_grackle_init_device; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo grackle_pci_host_info = { +diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c +index b9c2dcf..20cc682 100644 +--- a/hw/pci-host/piix.c ++++ b/hw/pci-host/piix.c +@@ -636,7 +636,6 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) + + k->init = i440fx_pcihost_initfn; + dc->fw_name = "pci"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo i440fx_pcihost_info = { +diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c +index eec538e..cdb401f 100644 +--- a/hw/pci-host/prep.c ++++ b/hw/pci-host/prep.c +@@ -213,7 +213,6 @@ static void raven_pcihost_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->realize = raven_pcihost_realizefn; + dc->fw_name = "pci"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo raven_pcihost_info = { +diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c +index 42b6367..0cc840e 100644 +--- a/hw/ppc/spapr_vio.c ++++ b/hw/ppc/spapr_vio.c +@@ -529,11 +529,9 @@ static int spapr_vio_bridge_init(SysBusDevice *dev) + + static void spapr_vio_bridge_class_init(ObjectClass *klass, void *data) + { +- DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = spapr_vio_bridge_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo spapr_vio_bridge_info = { +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index f86a4af..cc29d8e 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -181,7 +181,6 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data) + k->init = s390_ipl_init; + dc->props = s390_ipl_properties; + dc->reset = s390_ipl_reset; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo s390_ipl_info = { +diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c +index 9078bfb..2fce4c5 100644 +--- a/hw/s390x/s390-virtio-bus.c ++++ b/hw/s390x/s390-virtio-bus.c +@@ -675,11 +675,9 @@ static int s390_virtio_bridge_init(SysBusDevice *dev) + + static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) + { +- DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = s390_virtio_bridge_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo s390_virtio_bridge_info = { +diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c +index 74eb559..d981101 100644 +--- a/hw/s390x/virtio-ccw.c ++++ b/hw/s390x/virtio-ccw.c +@@ -1071,11 +1071,9 @@ static int virtual_css_bridge_init(SysBusDevice *dev) + + static void virtual_css_bridge_class_init(ObjectClass *klass, void *data) + { +- DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = virtual_css_bridge_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo virtual_css_bridge_info = { +diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c +index 95e4587..c5ad890 100644 +--- a/hw/sd/pl181.c ++++ b/hw/sd/pl181.c +@@ -497,7 +497,6 @@ static void pl181_class_init(ObjectClass *klass, void *data) + sdc->init = pl181_init; + k->vmsd = &vmstate_pl181; + k->reset = pl181_reset; +- k->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo pl181_info = { +diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c +index 6b088fa..aab4ae4 100644 +--- a/hw/timer/arm_mptimer.c ++++ b/hw/timer/arm_mptimer.c +@@ -290,7 +290,6 @@ static void arm_mptimer_class_init(ObjectClass *klass, void *data) + sbc->init = arm_mptimer_init; + dc->vmsd = &vmstate_arm_mptimer; + dc->reset = arm_mptimer_reset; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->props = arm_mptimer_properties; + } + +diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c +index 3f7f457..dd486a1 100644 +--- a/hw/timer/hpet.c ++++ b/hw/timer/hpet.c +@@ -739,7 +739,6 @@ static void hpet_device_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = hpet_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->reset = hpet_reset; + dc->vmsd = &vmstate_hpet; + dc->props = hpet_device_properties; +diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c +index aa9c5a6..241e7c8 100644 +--- a/hw/timer/pl031.c ++++ b/hw/timer/pl031.c +@@ -246,7 +246,6 @@ static void pl031_class_init(ObjectClass *klass, void *data) + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pl031_init; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_pl031; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-target-i386-Disable-PMU-CPUID-leaf-by-default.patch b/SOURCES/kvm-target-i386-Disable-PMU-CPUID-leaf-by-default.patch new file mode 100644 index 0000000..fa45f83 --- /dev/null +++ b/SOURCES/kvm-target-i386-Disable-PMU-CPUID-leaf-by-default.patch @@ -0,0 +1,122 @@ +From 99ce2407227bd5474e69c93ab0f061f2a3438eac Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Fri, 2 Aug 2013 14:08:52 +0200 +Subject: target-i386: Disable PMU CPUID leaf by default + +RH-Author: Eduardo Habkost +Message-id: <1375452533-12507-3-git-send-email-ehabkost@redhat.com> +Patchwork-id: 52933 +O-Subject: [RHEL-7 PATCH 2/3] target-i386: Disable PMU CPUID leaf by default +Bugzilla: 853101 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Gleb Natapov + +Bugzilla: 853101 + +Bug description: QEMU currently gets all bits from GET_SUPPORTED_CPUID +for CPUID leaf 0xA and passes them directly to the guest. This makes +the guest ABI depend on host kernel and host CPU capabilities, and +breaks live migration if we migrate between hosts with different +capabilities (e.g., different number of PMU counters). + +Add a "pmu" property to X86CPU, and set it to true only on "-cpu host", +or on pc-*-1.5 and older machine-types. + +For now, setting pmu=on will enable the current passthrough mode that +doesn't have any ABI stability guarantees, but in the future we may +implement a mode where the PMU CPUID bits are stable and configurable. + +Signed-off-by: Eduardo Habkost +Cc: Paolo Bonzini +Signed-off-by: Andreas Färber +(cherry picked from commit 9337e3b6e1d779215423d9b419d42200506deaab) +Signed-off-by: Eduardo Habkost + +Conflicts: + include/hw/i386/pc.h + target-i386/cpu.c + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 6692728..45487ba 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -211,6 +211,10 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); + .driver = "Nehalem-" TYPE_X86_CPU,\ + .property = "level",\ + .value = stringify(2),\ ++ },{\ ++ .driver = TYPE_X86_CPU,\ ++ .property = "pmu",\ ++ .value = "on",\ + } + + #define PC_COMPAT_1_4 \ +diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h +index 849cedf..5231005 100644 +--- a/target-i386/cpu-qom.h ++++ b/target-i386/cpu-qom.h +@@ -68,6 +68,13 @@ typedef struct X86CPU { + + /* Features that were filtered out because of missing host capabilities */ + uint32_t filtered_features[FEATURE_WORDS]; ++ ++ /* Enable PMU CPUID bits. This can't be enabled by default yet because ++ * it doesn't have ABI stability guarantees, as it passes all PMU CPUID ++ * bits returned by GET_SUPPORTED_CPUID (that depend on host CPU and kernel ++ * capabilities) directly to the guest. ++ */ ++ bool enable_pmu; + } X86CPU; + + static inline X86CPU *x86_env_get_cpu(CPUX86State *env) +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 0c9a99a..2bcc21e 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -1479,6 +1479,7 @@ static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def, + const char *name) + { + x86_def_t *def; ++ Error *err = NULL; + int i; + + if (name == NULL) { +@@ -1486,6 +1487,8 @@ static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def, + } + if (kvm_enabled() && strcmp(name, "host") == 0) { + kvm_cpu_fill_host(x86_cpu_def); ++ object_property_set_bool(OBJECT(cpu), true, "pmu", &err); ++ assert_no_error(err); + return 0; + } + +@@ -2017,7 +2020,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + break; + case 0xA: + /* Architectural Performance Monitoring Leaf */ +- if (kvm_enabled()) { ++ if (kvm_enabled() && cpu->enable_pmu) { + KVMState *s = cs->kvm_state; + + *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); +@@ -2506,6 +2509,11 @@ static int64_t x86_cpu_get_arch_id(CPUState *cs) + return env->cpuid_apic_id; + } + ++static Property x86_cpu_properties[] = { ++ DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), ++ DEFINE_PROP_END_OF_LIST() ++}; ++ + static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + { + X86CPUClass *xcc = X86_CPU_CLASS(oc); +@@ -2515,6 +2523,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) + xcc->parent_realize = dc->realize; + dc->realize = x86_cpu_realizefn; + dc->bus_type = TYPE_ICC_BUS; ++ dc->props = x86_cpu_properties; + + xcc->parent_reset = cc->reset; + cc->reset = x86_cpu_reset; diff --git a/SOURCES/kvm-target-i386-Pass-X86CPU-object-to-cpu_x86_find_by_name.patch b/SOURCES/kvm-target-i386-Pass-X86CPU-object-to-cpu_x86_find_by_name.patch new file mode 100644 index 0000000..aed3676 --- /dev/null +++ b/SOURCES/kvm-target-i386-Pass-X86CPU-object-to-cpu_x86_find_by_name.patch @@ -0,0 +1,48 @@ +From 72dbf6a170042cdeccc37ef106df264a48631d71 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Fri, 2 Aug 2013 14:08:51 +0200 +Subject: target-i386: Pass X86CPU object to cpu_x86_find_by_name() + +RH-Author: Eduardo Habkost +Message-id: <1375452533-12507-2-git-send-email-ehabkost@redhat.com> +Patchwork-id: 52932 +O-Subject: [RHEL-7 PATCH 1/3] target-i386: Pass X86CPU object to cpu_x86_find_by_name() +Bugzilla: 853101 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Gleb Natapov + +Bugzilla: 853101 + +This will help us change the initialization code to not require carrying +some intermediate values in a x86_def_t struct (and eventually kill the +x86_def_t struct entirely). + +Signed-off-by: Eduardo Habkost +Signed-off-by: Andreas Färber +(cherry picked from commit c139911261c5acc9dae56b1180db320ba25636bd) +Signed-off-by: Eduardo Habkost + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 4b2da0d..0c9a99a 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -1475,7 +1475,8 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque, + error_propagate(errp, err); + } + +-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) ++static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def, ++ const char *name) + { + x86_def_t *def; + int i; +@@ -1742,7 +1743,7 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp) + + memset(def, 0, sizeof(*def)); + +- if (cpu_x86_find_by_name(def, name) < 0) { ++ if (cpu_x86_find_by_name(cpu, def, name) < 0) { + error_setg(errp, "Unable to find CPU definition: %s", name); + return; + } diff --git a/SOURCES/kvm-target-i386-Set-model-6-on-qemu64-qemu32-CPU-models.patch b/SOURCES/kvm-target-i386-Set-model-6-on-qemu64-qemu32-CPU-models.patch new file mode 100644 index 0000000..0178ace --- /dev/null +++ b/SOURCES/kvm-target-i386-Set-model-6-on-qemu64-qemu32-CPU-models.patch @@ -0,0 +1,105 @@ +From 9baf8dbaac5707b25f9126a5ba06716efe6793d5 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 17 Oct 2013 10:38:42 +0200 +Subject: [PATCH 05/25] target-i386: Set model=6 on qemu64 & qemu32 CPU models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Message-id: <1379363997-11783-2-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54398 +O-Subject: [RHEL7 PATCH 1/4] target-i386: Set model=6 on qemu64 & qemu32 CPU models +Bugzilla: 1004290 +RH-Acked-by: Bandan Das +RH-Acked-by: Markus Armbruster +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1004290 +Upstream status: commit f8e6a11aecc96e9d8a84f17d7c07019471714e20. +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6290888 + +There's no Intel CPU with family=6,model=2, and Linux and Windows guests +disable SEP when seeing that combination due to Pentium Pro erratum #82. + +In addition to just having SEP ignored by guests, Skype (and maybe other +applications) runs sysenter directly without passing through ntdll on +Windows, and crashes because Windows ignored the SEP CPUID bit. + +So, having model > 2 is a better default on qemu64 and qemu32 for two +reasons: making SEP really available for guests, and avoiding crashing +applications that work on bare metal. + +model=3 would fix the problem, but it causes CPU enumeration problems +for Windows guests[1]. So let's set model=6, that matches "Athlon +(PM core)" on AMD and "P2 with on-die L2 cache" on Intel and it allows +Windows to use all CPUs as well as fixing sysenter. + +[1] https://bugzilla.redhat.com/show_bug.cgi?id=508623 + +Cc: Andrea Arcangeli +Signed-off-by: Eduardo Habkost +Reviewed-by: Igor Mammedov +Signed-off-by: Andreas Färber +(cherry picked from commit 5cb6eb263d92972b54f84e0acf75e7159de20498) +Signed-off-by: Eduardo Habkost + +Conflicts: + include/hw/i386/pc.h + +Backport notes: + * PC_COMPAT_1_6 does not exist on the RHEL-7 tree + * RHEL-6 already have model=6 on qemu64 since RHEL-6.0, but not on + qemu32, so PC_RHEL6_5_COMPAT includes only the qemu32 compat change + +Maintainer's notes: + * Cherry-picked from Andreas Färber's qom-cpu tree + * Upstream status valid for qemu tree +--- + hw/i386/pc_piix.c | 4 ++++ + target-i386/cpu.c | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) +--- + hw/i386/pc_piix.c | 4 ++++ + target-i386/cpu.c | 4 ++-- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index a19f155..39be127 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -861,6 +861,10 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "level",\ + .value = stringify(0),\ + },{\ ++ .driver = "qemu32-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(3),\ ++ },{\ + .driver = "usb-ccid",\ + .property = "serial",\ + .value = "1",\ +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index a0358c0..170a46c 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -434,7 +434,7 @@ static x86_def_t builtin_x86_defs[] = { + .level = 4, + .vendor = CPUID_VENDOR_AMD, + .family = 6, +- .model = 2, ++ .model = 6, + .stepping = 3, + .features[FEAT_1_EDX] = + PPRO_FEATURES | +@@ -537,7 +537,7 @@ static x86_def_t builtin_x86_defs[] = { + .level = 4, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +- .model = 3, ++ .model = 6, + .stepping = 3, + .features[FEAT_1_EDX] = + PPRO_FEATURES, +-- +1.7.1 + diff --git a/SOURCES/kvm-target-i386-add-cpu64-rhel6-CPU-model.patch b/SOURCES/kvm-target-i386-add-cpu64-rhel6-CPU-model.patch new file mode 100644 index 0000000..8cc5bf1 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-cpu64-rhel6-CPU-model.patch @@ -0,0 +1,72 @@ +From b0e92beaf0cd1146d417bff8241940762ab3d60f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Wed, 18 Sep 2013 20:49:59 +0200 +Subject: [PATCH 28/29] target-i386: add cpu64-rhel6 CPU model + +RH-Author: Eduardo Habkost +Message-id: <1379537399-7308-1-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54451 +O-Subject: [RHEL-7 qemu-kvm PATCH] target-i386: add cpu64-rhel6 CPU model +Bugzilla: 918907 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +Bugzilla: 918907 +Upstream status: not applicable +Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6300787 + +RHEL-6 has a cpu64-rhel6 CPU model, and it is even the default CPU +model. We need to allow migration from RHEL-6, so we need to have a +compatible cpu64-rhel6 CPU model to be present. + +Signed-off-by: Eduardo Habkost +--- +Change v1 -> v2: + - Don't include cpu64-rhel5 CPU model. It won't be supported +--- + target-i386/cpu.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 23 +++++++++++++++++++++++ + 1 files changed, 23 insertions(+), 0 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 355375b..051ab39 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -668,6 +668,29 @@ static x86_def_t builtin_x86_defs[] = { + .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", + }, + { ++ .name = "cpu64-rhel6", ++ .level = 4, ++ .vendor = CPUID_VENDOR_AMD, ++ .family = 6, ++ .model = 13, ++ .stepping = 3, ++ .features[FEAT_1_EDX] = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | ++ CPUID_MMX | CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | ++ CPUID_MCA | CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | ++ CPUID_CX8 | CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | ++ CPUID_PSE | CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = CPUID_EXT_CX16 | CPUID_EXT_SSE3, ++ .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_FXSR | ++ CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PAT | CPUID_EXT2_CMOV | ++ CPUID_EXT2_PGE | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC | ++ CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | ++ CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU, ++ .features[FEAT_8000_0001_ECX] = CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | ++ CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, ++ .xlevel = 0x8000000A, ++ .model_id = "QEMU Virtual CPU version (cpu64-rhel6)", ++ }, ++ { + .name = "Conroe", + .level = 4, + .vendor = CPUID_VENDOR_INTEL, +-- +1.7.1 + diff --git a/SOURCES/kvm-target-i386-add-feature-kvm_pv_unhalt.patch b/SOURCES/kvm-target-i386-add-feature-kvm_pv_unhalt.patch new file mode 100644 index 0000000..521c5a2 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-feature-kvm_pv_unhalt.patch @@ -0,0 +1,56 @@ +From 7a204d6f5d8286fe56f91236aa72c26ec367d39b Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Tue, 24 Sep 2013 13:08:53 +0200 +Subject: [PATCH 04/11] target-i386: add feature kvm_pv_unhalt +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Andrew Jones +Message-id: <1380028133-15578-3-git-send-email-drjones@redhat.com> +Patchwork-id: 54525 +O-Subject: [RHEL7.0 qemu-kvm PATCH 2/2] target-i386: add feature kvm_pv_unhalt +Bugzilla: 1008987 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Igor Mammedov +RH-Acked-by: Radim Krcmar + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1008987 + +(cherry picked from commit f010bc643a2759e87e989c3e4e85f15ec71ae98f + of uq/master) + +=== + +I don't know yet if want this feature on by default, so for now I'm +just adding support for "-cpu ...,+kvm_pv_unhalt". + +Signed-off-by: Andrew Jones +Reviewed-by: Eduardo Habkost +Reviewed-by: Andreas Färber +Signed-off-by: Paolo Bonzini +--- + target-i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 051ab39..a0358c0 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -125,7 +125,7 @@ static const char *ext4_feature_name[] = { + + static const char *kvm_feature_name[] = { + "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", +- "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", NULL, ++ "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", "kvm_pv_unhalt", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.7.1 + diff --git a/SOURCES/kvm-target-i386-remove-tabs-from-target-i386-cpu.h.patch b/SOURCES/kvm-target-i386-remove-tabs-from-target-i386-cpu.h.patch new file mode 100644 index 0000000..384d922 --- /dev/null +++ b/SOURCES/kvm-target-i386-remove-tabs-from-target-i386-cpu.h.patch @@ -0,0 +1,304 @@ +From 1f49705e06366e1c2fa2b2c77497ed33ca1c6a30 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 23 Sep 2013 17:06:11 +0200 +Subject: [PATCH 01/29] target-i386: remove tabs from target-i386/cpu.h + +RH-Author: Paolo Bonzini +Message-id: <1379955972-3080-2-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54486 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 1/2] target-i386: remove tabs from target-i386/cpu.h +Bugzilla: 928867 +RH-Acked-by: Juan Quintela +RH-Acked-by: Marcelo Tosatti +RH-Acked-by: Bandan Das + +Signed-off-by: Paolo Bonzini +(cherry-picked from commit e4a09c9637f13a744ad7e2bc5223df05ac582c0d) +--- + target-i386/cpu.h | 192 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 96 insertions(+), 96 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.h | 192 ++++++++++++++++++++++++++-------------------------- + 1 files changed, 96 insertions(+), 96 deletions(-) + +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 058c57f..74c7899 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -37,9 +37,9 @@ + #define TARGET_HAS_ICE 1 + + #ifdef TARGET_X86_64 +-#define ELF_MACHINE EM_X86_64 ++#define ELF_MACHINE EM_X86_64 + #else +-#define ELF_MACHINE EM_386 ++#define ELF_MACHINE EM_386 + #endif + + #define CPUArchState struct CPUX86State +@@ -98,10 +98,10 @@ + #define DESC_TSS_BUSY_MASK (1 << 9) + + /* eflags masks */ +-#define CC_C 0x0001 +-#define CC_P 0x0004 +-#define CC_A 0x0010 +-#define CC_Z 0x0040 ++#define CC_C 0x0001 ++#define CC_P 0x0004 ++#define CC_A 0x0010 ++#define CC_Z 0x0040 + #define CC_S 0x0080 + #define CC_O 0x0800 + +@@ -109,14 +109,14 @@ + #define IOPL_SHIFT 12 + #define VM_SHIFT 17 + +-#define TF_MASK 0x00000100 +-#define IF_MASK 0x00000200 +-#define DF_MASK 0x00000400 +-#define IOPL_MASK 0x00003000 +-#define NT_MASK 0x00004000 +-#define RF_MASK 0x00010000 +-#define VM_MASK 0x00020000 +-#define AC_MASK 0x00040000 ++#define TF_MASK 0x00000100 ++#define IF_MASK 0x00000200 ++#define DF_MASK 0x00000400 ++#define IOPL_MASK 0x00003000 ++#define NT_MASK 0x00004000 ++#define RF_MASK 0x00010000 ++#define VM_MASK 0x00020000 ++#define AC_MASK 0x00040000 + #define VIF_MASK 0x00080000 + #define VIP_MASK 0x00100000 + #define ID_MASK 0x00200000 +@@ -238,28 +238,28 @@ + #define DR7_TYPE_IO_RW 0x2 + #define DR7_TYPE_DATA_RW 0x3 + +-#define PG_PRESENT_BIT 0 +-#define PG_RW_BIT 1 +-#define PG_USER_BIT 2 +-#define PG_PWT_BIT 3 +-#define PG_PCD_BIT 4 +-#define PG_ACCESSED_BIT 5 +-#define PG_DIRTY_BIT 6 +-#define PG_PSE_BIT 7 +-#define PG_GLOBAL_BIT 8 +-#define PG_NX_BIT 63 ++#define PG_PRESENT_BIT 0 ++#define PG_RW_BIT 1 ++#define PG_USER_BIT 2 ++#define PG_PWT_BIT 3 ++#define PG_PCD_BIT 4 ++#define PG_ACCESSED_BIT 5 ++#define PG_DIRTY_BIT 6 ++#define PG_PSE_BIT 7 ++#define PG_GLOBAL_BIT 8 ++#define PG_NX_BIT 63 + + #define PG_PRESENT_MASK (1 << PG_PRESENT_BIT) +-#define PG_RW_MASK (1 << PG_RW_BIT) +-#define PG_USER_MASK (1 << PG_USER_BIT) +-#define PG_PWT_MASK (1 << PG_PWT_BIT) +-#define PG_PCD_MASK (1 << PG_PCD_BIT) ++#define PG_RW_MASK (1 << PG_RW_BIT) ++#define PG_USER_MASK (1 << PG_USER_BIT) ++#define PG_PWT_MASK (1 << PG_PWT_BIT) ++#define PG_PCD_MASK (1 << PG_PCD_BIT) + #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT) +-#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) +-#define PG_PSE_MASK (1 << PG_PSE_BIT) +-#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) ++#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) ++#define PG_PSE_MASK (1 << PG_PSE_BIT) ++#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) + #define PG_HI_USER_MASK 0x7ff0000000000000LL +-#define PG_NX_MASK (1LL << PG_NX_BIT) ++#define PG_NX_MASK (1LL << PG_NX_BIT) + + #define PG_ERROR_W_BIT 1 + +@@ -269,32 +269,32 @@ + #define PG_ERROR_RSVD_MASK 0x08 + #define PG_ERROR_I_D_MASK 0x10 + +-#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ +-#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ ++#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ ++#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ + +-#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P) +-#define MCE_BANKS_DEF 10 ++#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P) ++#define MCE_BANKS_DEF 10 + +-#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ +-#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */ +-#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ ++#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ ++#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */ ++#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ + +-#define MCI_STATUS_VAL (1ULL<<63) /* valid error */ +-#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ +-#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ +-#define MCI_STATUS_EN (1ULL<<60) /* error enabled */ +-#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */ +-#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */ +-#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ +-#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ +-#define MCI_STATUS_AR (1ULL<<55) /* Action required */ ++#define MCI_STATUS_VAL (1ULL<<63) /* valid error */ ++#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ ++#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ ++#define MCI_STATUS_EN (1ULL<<60) /* error enabled */ ++#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */ ++#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */ ++#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ ++#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ ++#define MCI_STATUS_AR (1ULL<<55) /* Action required */ + + /* MISC register defines */ +-#define MCM_ADDR_SEGOFF 0 /* segment offset */ +-#define MCM_ADDR_LINEAR 1 /* linear address */ +-#define MCM_ADDR_PHYS 2 /* physical address */ +-#define MCM_ADDR_MEM 3 /* memory address */ +-#define MCM_ADDR_GENERIC 7 /* generic */ ++#define MCM_ADDR_SEGOFF 0 /* segment offset */ ++#define MCM_ADDR_LINEAR 1 /* linear address */ ++#define MCM_ADDR_PHYS 2 /* physical address */ ++#define MCM_ADDR_MEM 3 /* memory address */ ++#define MCM_ADDR_GENERIC 7 /* generic */ + + #define MSR_IA32_TSC 0x10 + #define MSR_IA32_APICBASE 0x1b +@@ -304,10 +304,10 @@ + #define MSR_TSC_ADJUST 0x0000003b + #define MSR_IA32_TSCDEADLINE 0x6e0 + +-#define MSR_MTRRcap 0xfe +-#define MSR_MTRRcap_VCNT 8 +-#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) +-#define MSR_MTRRcap_WC_SUPPORTED (1 << 10) ++#define MSR_MTRRcap 0xfe ++#define MSR_MTRRcap_VCNT 8 ++#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) ++#define MSR_MTRRcap_WC_SUPPORTED (1 << 10) + + #define MSR_IA32_SYSENTER_CS 0x174 + #define MSR_IA32_SYSENTER_ESP 0x175 +@@ -319,33 +319,33 @@ + + #define MSR_IA32_PERF_STATUS 0x198 + +-#define MSR_IA32_MISC_ENABLE 0x1a0 ++#define MSR_IA32_MISC_ENABLE 0x1a0 + /* Indicates good rep/movs microcode on some processors: */ + #define MSR_IA32_MISC_ENABLE_DEFAULT 1 + +-#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) +-#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) +- +-#define MSR_MTRRfix64K_00000 0x250 +-#define MSR_MTRRfix16K_80000 0x258 +-#define MSR_MTRRfix16K_A0000 0x259 +-#define MSR_MTRRfix4K_C0000 0x268 +-#define MSR_MTRRfix4K_C8000 0x269 +-#define MSR_MTRRfix4K_D0000 0x26a +-#define MSR_MTRRfix4K_D8000 0x26b +-#define MSR_MTRRfix4K_E0000 0x26c +-#define MSR_MTRRfix4K_E8000 0x26d +-#define MSR_MTRRfix4K_F0000 0x26e +-#define MSR_MTRRfix4K_F8000 0x26f ++#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) ++#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) ++ ++#define MSR_MTRRfix64K_00000 0x250 ++#define MSR_MTRRfix16K_80000 0x258 ++#define MSR_MTRRfix16K_A0000 0x259 ++#define MSR_MTRRfix4K_C0000 0x268 ++#define MSR_MTRRfix4K_C8000 0x269 ++#define MSR_MTRRfix4K_D0000 0x26a ++#define MSR_MTRRfix4K_D8000 0x26b ++#define MSR_MTRRfix4K_E0000 0x26c ++#define MSR_MTRRfix4K_E8000 0x26d ++#define MSR_MTRRfix4K_F0000 0x26e ++#define MSR_MTRRfix4K_F8000 0x26f + + #define MSR_PAT 0x277 + +-#define MSR_MTRRdefType 0x2ff ++#define MSR_MTRRdefType 0x2ff + +-#define MSR_MC0_CTL 0x400 +-#define MSR_MC0_STATUS 0x401 +-#define MSR_MC0_ADDR 0x402 +-#define MSR_MC0_MISC 0x403 ++#define MSR_MC0_CTL 0x400 ++#define MSR_MC0_STATUS 0x401 ++#define MSR_MC0_ADDR 0x402 ++#define MSR_MC0_MISC 0x403 + + #define MSR_EFER 0xc0000080 + +@@ -549,24 +549,24 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ + #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ + +-#define EXCP00_DIVZ 0 +-#define EXCP01_DB 1 +-#define EXCP02_NMI 2 +-#define EXCP03_INT3 3 +-#define EXCP04_INTO 4 +-#define EXCP05_BOUND 5 +-#define EXCP06_ILLOP 6 +-#define EXCP07_PREX 7 +-#define EXCP08_DBLE 8 +-#define EXCP09_XERR 9 +-#define EXCP0A_TSS 10 +-#define EXCP0B_NOSEG 11 +-#define EXCP0C_STACK 12 +-#define EXCP0D_GPF 13 +-#define EXCP0E_PAGE 14 +-#define EXCP10_COPR 16 +-#define EXCP11_ALGN 17 +-#define EXCP12_MCHK 18 ++#define EXCP00_DIVZ 0 ++#define EXCP01_DB 1 ++#define EXCP02_NMI 2 ++#define EXCP03_INT3 3 ++#define EXCP04_INTO 4 ++#define EXCP05_BOUND 5 ++#define EXCP06_ILLOP 6 ++#define EXCP07_PREX 7 ++#define EXCP08_DBLE 8 ++#define EXCP09_XERR 9 ++#define EXCP0A_TSS 10 ++#define EXCP0B_NOSEG 11 ++#define EXCP0C_STACK 12 ++#define EXCP0D_GPF 13 ++#define EXCP0E_PAGE 14 ++#define EXCP10_COPR 16 ++#define EXCP11_ALGN 17 ++#define EXCP12_MCHK 18 + + #define EXCP_SYSCALL 0x100 /* only happens in user only emulation + for syscall instruction */ +@@ -1085,7 +1085,7 @@ static inline CPUX86State *cpu_init(const char *cpu_model) + #define cpu_gen_code cpu_x86_gen_code + #define cpu_signal_handler cpu_x86_signal_handler + #define cpu_list x86_cpu_list +-#define cpudef_setup x86_cpudef_setup ++#define cpudef_setup x86_cpudef_setup + + /* MMU modes definitions */ + #define MMU_MODE0_SUFFIX _kernel +-- +1.7.1 + diff --git a/SOURCES/kvm-target-i386-support-loading-of-cpu-xsave-subsection.patch b/SOURCES/kvm-target-i386-support-loading-of-cpu-xsave-subsection.patch new file mode 100644 index 0000000..c712bba --- /dev/null +++ b/SOURCES/kvm-target-i386-support-loading-of-cpu-xsave-subsection.patch @@ -0,0 +1,84 @@ +From c437843790b9b21a90a41b6d96b2b6db3be3d33a Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Wed, 16 Oct 2013 20:00:44 +0200 +Subject: [PATCH 18/18] target-i386: support loading of "cpu/xsave" subsection + +RH-Author: Eduardo Habkost +Message-id: <1381953644-6411-1-git-send-email-ehabkost@redhat.com> +Patchwork-id: 54966 +O-Subject: [qemu-kvm RHEL7 PATCH] target-i386: support loading of "cpu/xsave" subsection +Bugzilla: 1004743 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Juan Quintela +RH-Acked-by: Orit Wasserman + +Bugzilla: 1004743 +Scratch build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6429524 +Upstream status: not applicable + (We could try to make upstream accept the subsection, but I don't + think it will be accepted because there's no real benefit) + +This is a kind of forward-port of RHEL-6 commits ceee3a15c8 and 7f468b80fd, so +the "cpu/xsave" subsection can be loaded when migrating from RHEL-6. + +The differences between the RHEL-6 patches and this one are: + * The xsave state is not being removed from the main "cpu" section, + so we keep using the same format/version used upstream + * The subsection is always reported as optional, because the xsave + state is kept in the main "cpu" section + +Signed-off-by: Eduardo Habkost +--- + target-i386/machine.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/machine.c | 24 +++++++++++++++++++++++- + 1 files changed, 23 insertions(+), 1 deletions(-) + +diff --git a/target-i386/machine.c b/target-i386/machine.c +index 8faea62..4f30347 100644 +--- a/target-i386/machine.c ++++ b/target-i386/machine.c +@@ -446,6 +446,25 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = { + } + }; + ++static bool vmstate_xsave_needed(void *opaque) ++{ ++ /* The xsave state is already on the main "cpu" section */ ++ return false; ++} ++ ++static const VMStateDescription vmstate_xsave ={ ++ .name = "cpu/xsave", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .minimum_version_id_old = 1, ++ .fields = (VMStateField []) { ++ VMSTATE_UINT64_V(env.xcr0, X86CPU, 1), ++ VMSTATE_UINT64_V(env.xstate_bv, X86CPU, 1), ++ VMSTATE_YMMH_REGS_VARS(env.ymmh_regs, X86CPU, CPU_NB_REGS, 1), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + const VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -571,7 +590,10 @@ const VMStateDescription vmstate_x86_cpu = { + }, { + .vmsd = &vmstate_msr_ia32_misc_enable, + .needed = misc_enable_needed, +- } , { ++ }, { ++ .vmsd = &vmstate_xsave, ++ .needed = vmstate_xsave_needed, ++ }, { + /* empty */ + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-tests-set-MALLOC_PERTURB_-to-expose-memory-bugs.patch b/SOURCES/kvm-tests-set-MALLOC_PERTURB_-to-expose-memory-bugs.patch new file mode 100644 index 0000000..9463544 --- /dev/null +++ b/SOURCES/kvm-tests-set-MALLOC_PERTURB_-to-expose-memory-bugs.patch @@ -0,0 +1,79 @@ +From 5178597af3139c1ce9ac95971729468eda5625d7 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Mon, 27 May 2013 15:28:51 +0200 +Subject: [PATCH 34/38] tests: set MALLOC_PERTURB_ to expose memory bugs + +Message-id: <1379499002-5231-3-git-send-email-mreitz@redhat.com> +Patchwork-id: 54433 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 2/6] tests: set MALLOC_PERTURB_ to expose memory bugs +Bugzilla: 1006959 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +BZ: 1006959 + +glibc wipes malloc(3) memory when the MALLOC_PERTURB_ environment +variable is set. The value of the environment variable determines the +bit pattern used to wipe memory. For more information, see +http://udrepper.livejournal.com/11429.html. + +Set MALLOC_PERTURB_ for gtester and qemu-iotests. Note we pick a random +value from 1 to 255 to expose more bugs. If you need to reproduce a +crash use 'show environment' in gdb to extract the MALLOC_PERTURB_ +value from a core dump. + +Both make check and qemu-iotests pass with MALLOC_PERTURB_ enabled. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Eric Blake +Message-id: 1369661331-28041-1-git-send-email-stefanha@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 04129606170ec9011d4952b4f22c368679bedbf9) + +Signed-off-by: Max Reitz +--- + tests/Makefile | 5 ++++- + tests/qemu-iotests/check | 3 ++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/tests/Makefile b/tests/Makefile +index a307d5a..c107489 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -171,6 +171,7 @@ GCOV_OPTIONS = -n $(if $(V),-f,) + $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y) + $(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,) + $(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \ ++ MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \ + gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@") + $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y); do \ + echo Gcov report for $$f:;\ +@@ -180,7 +181,9 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y) + .PHONY: $(patsubst %, check-%, $(check-unit-y)) + $(patsubst %, check-%, $(check-unit-y)): check-%: % + $(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,) +- $(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*") ++ $(call quiet-command, \ ++ MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \ ++ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*") + $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y); do \ + echo Gcov report for $$f:;\ + $(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \ +diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check +index 432732c..74628ae 100755 +--- a/tests/qemu-iotests/check ++++ b/tests/qemu-iotests/check +@@ -214,7 +214,8 @@ do + start=`_wallclock` + $timestamp && echo -n " ["`date "+%T"`"]" + [ ! -x $seq ] && chmod u+x $seq # ensure we can run it +- ./$seq >$tmp.out 2>&1 ++ MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \ ++ ./$seq >$tmp.out 2>&1 + sts=$? + $timestamp && _timestamp + stop=`_wallclock` +-- +1.7.1 + diff --git a/SOURCES/kvm-usb-add-serial-bus-property.patch b/SOURCES/kvm-usb-add-serial-bus-property.patch new file mode 100644 index 0000000..7cc03cc --- /dev/null +++ b/SOURCES/kvm-usb-add-serial-bus-property.patch @@ -0,0 +1,143 @@ +From b853920b298d19a1905d106c7d965bda29b7a26c Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 2 Sep 2013 13:26:15 +0200 +Subject: [PATCH 09/29] usb: add serial bus property + +RH-Author: Gerd Hoffmann +Message-id: <1378128376-25930-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 53989 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/2] usb: add serial bus property +Bugzilla: 953304 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Hans de Goede +RH-Acked-by: Paolo Bonzini + +This patch adds a serial property for all usb devices, which can be +used to set the serial number of a usb device (as listed by lsusb -v) +to a specific value. Applies to emulated devices only. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 71938a09d2b9fd4007515fec6c395916cb08f868) +--- + hw/usb/bus.c | 1 + + hw/usb/desc.c | 6 ++++++ + hw/usb/dev-hid.c | 3 +++ + hw/usb/dev-storage.c | 13 +++---------- + include/hw/usb.h | 1 + + 5 files changed, 14 insertions(+), 10 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/bus.c | 1 + + hw/usb/desc.c | 6 ++++++ + hw/usb/dev-hid.c | 3 +++ + hw/usb/dev-storage.c | 13 +++---------- + include/hw/usb.h | 1 + + 5 files changed, 14 insertions(+), 10 deletions(-) + +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index d1827be..f83d1de 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -13,6 +13,7 @@ static int usb_qdev_exit(DeviceState *qdev); + + static Property usb_props[] = { + DEFINE_PROP_STRING("port", USBDevice, port_path), ++ DEFINE_PROP_STRING("serial", USBDevice, serial), + DEFINE_PROP_BIT("full-path", USBDevice, flags, + USB_DEV_FLAG_FULL_PATH, true), + DEFINE_PROP_END_OF_LIST() +diff --git a/hw/usb/desc.c b/hw/usb/desc.c +index fce303e..bf6c522 100644 +--- a/hw/usb/desc.c ++++ b/hw/usb/desc.c +@@ -566,6 +566,12 @@ void usb_desc_create_serial(USBDevice *dev) + char *path; + int dst; + ++ if (dev->serial) { ++ /* 'serial' usb bus property has priority if present */ ++ usb_desc_set_string(dev, index, dev->serial); ++ return; ++ } ++ + assert(index != 0 && desc->str[index] != NULL); + dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]); + path = qdev_get_dev_path(hcd); +diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c +index b48899d..31f3cde 100644 +--- a/hw/usb/dev-hid.c ++++ b/hw/usb/dev-hid.c +@@ -560,6 +560,9 @@ static int usb_hid_initfn(USBDevice *dev, int kind) + { + USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + ++ if (dev->serial) { ++ usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial); ++ } + usb_desc_init(dev); + us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); + hid_init(&us->hid, kind, usb_hid_changed); +diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c +index 1073901..fe914ab 100644 +--- a/hw/usb/dev-storage.c ++++ b/hw/usb/dev-storage.c +@@ -58,7 +58,6 @@ typedef struct { + USBPacket *packet; + /* usb-storage only */ + BlockConf conf; +- char *serial; + uint32_t removable; + } MSDState; + +@@ -602,7 +601,7 @@ static int usb_msd_initfn_storage(USBDevice *dev) + return -1; + } + +- blkconf_serial(&s->conf, &s->serial); ++ blkconf_serial(&s->conf, &dev->serial); + + /* + * Hack alert: this pretends to be a block device, but it's really +@@ -616,16 +615,11 @@ static int usb_msd_initfn_storage(USBDevice *dev) + bdrv_detach_dev(bs, &s->dev.qdev); + s->conf.bs = NULL; + +- if (s->serial) { +- usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial); +- } else { +- usb_desc_create_serial(dev); +- } +- ++ usb_desc_create_serial(dev); + usb_desc_init(dev); + scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL); + scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, +- s->conf.bootindex, s->serial); ++ s->conf.bootindex, dev->serial); + if (!scsi_dev) { + return -1; + } +@@ -734,7 +728,6 @@ static const VMStateDescription vmstate_usb_msd = { + + static Property msd_properties[] = { + DEFINE_BLOCK_PROPERTIES(MSDState, conf), +- DEFINE_PROP_STRING("serial", MSDState, serial), + DEFINE_PROP_BIT("removable", MSDState, removable, 0, false), + DEFINE_PROP_END_OF_LIST(), + }; +diff --git a/include/hw/usb.h b/include/hw/usb.h +index 4d9d05e..901b0da 100644 +--- a/include/hw/usb.h ++++ b/include/hw/usb.h +@@ -205,6 +205,7 @@ struct USBDevice { + DeviceState qdev; + USBPort *port; + char *port_path; ++ char *serial; + void *opaque; + uint32_t flags; + +-- +1.7.1 + diff --git a/SOURCES/kvm-usb-host-libusb-Configuration-0-may-be-a-valid-confi.patch b/SOURCES/kvm-usb-host-libusb-Configuration-0-may-be-a-valid-confi.patch new file mode 100644 index 0000000..952b11e --- /dev/null +++ b/SOURCES/kvm-usb-host-libusb-Configuration-0-may-be-a-valid-confi.patch @@ -0,0 +1,66 @@ +From 50120520c3ec6385d2d36f5f0fe37acf8d230e91 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 6 Nov 2013 12:16:59 +0100 +Subject: [PATCH 64/81] usb-host-libusb: Configuration 0 may be a valid configuration + +RH-Author: Gerd Hoffmann +Message-id: <1383740220-2049-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 55512 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/3] usb-host-libusb: Configuration 0 may be a valid configuration +Bugzilla: 980383 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Alex Williamson + +From: Hans de Goede + +Quoting from: linux/Documentation/ABI/stable/sysfs-bus-usb: + + Note that some devices, in violation of the USB spec, have a + configuration with a value equal to 0. Writing 0 to + bConfigurationValue for these devices will install that + configuration, rather then unconfigure the device. + +So don't compare the configuration value against 0 to check for unconfigured +devices, instead check for a LIBUSB_ERROR_NOT_FOUND return from +libusb_get_active_config_descriptor(). + +Signed-off-by: Hans de Goede +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 1294ca797c6bee39d4dbc3e92010873ce4047e0e) +--- + hw/usb/host-libusb.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/host-libusb.c | 9 ++++----- + 1 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 9c8905e..9b226e4 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -992,15 +992,14 @@ static int usb_host_claim_interfaces(USBHostDevice *s, int configuration) + udev->ninterfaces = 0; + udev->configuration = 0; + +- if (configuration == 0) { +- /* address state - ignore */ +- return USB_RET_SUCCESS; +- } +- + usb_host_detach_kernel(s); + + rc = libusb_get_active_config_descriptor(s->dev, &conf); + if (rc != 0) { ++ if (rc == LIBUSB_ERROR_NOT_FOUND) { ++ /* address state - ignore */ ++ return USB_RET_SUCCESS; ++ } + return USB_RET_STALL; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-usb-host-libusb-Detach-kernel-drivers-earlier.patch b/SOURCES/kvm-usb-host-libusb-Detach-kernel-drivers-earlier.patch new file mode 100644 index 0000000..95ff9ff --- /dev/null +++ b/SOURCES/kvm-usb-host-libusb-Detach-kernel-drivers-earlier.patch @@ -0,0 +1,70 @@ +From 13b8b9eda753aa5bc1758627f9148e4fff91f90f Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 6 Nov 2013 12:17:00 +0100 +Subject: [PATCH 65/81] usb-host-libusb: Detach kernel drivers earlier + +RH-Author: Gerd Hoffmann +Message-id: <1383740220-2049-4-git-send-email-kraxel@redhat.com> +Patchwork-id: 55515 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/3] usb-host-libusb: Detach kernel drivers earlier +Bugzilla: 980383 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Alex Williamson + +From: Hans de Goede + +If we detach the kernel drivers on the first set_config, then they will +be still attached when the device gets its initial reset. Causing the drivers +to re-initialize the device after the reset, dirtying the device state. + +Signed-off-by: Hans de Goede +Signed-off-by: Gerd Hoffmann +(cherry picked from commit f34d5c750897abb3853910ce73f63d88d74dc827) +--- + hw/usb/host-libusb.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/host-libusb.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 9b226e4..8510902 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -137,6 +137,7 @@ static QTAILQ_HEAD(, USBHostDevice) hostdevs = + static void usb_host_auto_check(void *unused); + static void usb_host_release_interfaces(USBHostDevice *s); + static void usb_host_nodev(USBHostDevice *s); ++static void usb_host_detach_kernel(USBHostDevice *s); + static void usb_host_attach_kernel(USBHostDevice *s); + + /* ------------------------------------------------------------------------ */ +@@ -787,10 +788,13 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev) + goto fail; + } + +- libusb_get_device_descriptor(dev, &s->ddesc); + s->dev = dev; + s->bus_num = bus_num; + s->addr = addr; ++ ++ usb_host_detach_kernel(s); ++ ++ libusb_get_device_descriptor(dev, &s->ddesc); + usb_host_get_port(s->dev, s->port, sizeof(s->port)); + + usb_ep_init(udev); +@@ -1051,7 +1055,6 @@ static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p) + trace_usb_host_set_config(s->bus_num, s->addr, config); + + usb_host_release_interfaces(s); +- usb_host_detach_kernel(s); + rc = libusb_set_configuration(s->dh, config); + if (rc != 0) { + usb_host_libusb_error("libusb_set_configuration", rc); +-- +1.7.1 + diff --git a/SOURCES/kvm-usb-host-libusb-Fix-building-with-libusb-git-master-code.patch b/SOURCES/kvm-usb-host-libusb-Fix-building-with-libusb-git-master-code.patch new file mode 100644 index 0000000..3657616 --- /dev/null +++ b/SOURCES/kvm-usb-host-libusb-Fix-building-with-libusb-git-master-code.patch @@ -0,0 +1,44 @@ +From 4de8173704a782b602f2d5412b2b9d08ceb9fc1d Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Tue, 13 Aug 2013 08:31:21 +0200 +Subject: usb/host-libusb: Fix building with libusb git master code + +RH-Author: Stefan Hajnoczi +Message-id: <1376382681-14630-1-git-send-email-stefanha@redhat.com> +Patchwork-id: 53201 +O-Subject: [PATCH] usb/host-libusb: Fix building with libusb git master code +Bugzilla: 996469 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Hans de Goede + +From: Hans de Goede + +Upstream-status: bc45de8c21dfc3bc3896a78b33d5a6d9e710dfff +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=6159903 +BZ: 996469 + +The next libusb release will deprecate libusb_get_port_path, and since +we compile with -Werror, this breaks the build. + +Signed-off-by: Hans de Goede +Signed-off-by: Gerd Hoffmann +(cherry picked from commit bc45de8c21dfc3bc3896a78b33d5a6d9e710dfff) +Signed-off-by: Stefan Hajnoczi + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 3a582c5..0c12b0f 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -241,7 +241,11 @@ static int usb_host_get_port(libusb_device *dev, char *port, size_t len) + size_t off; + int rc, i; + ++#if LIBUSBX_API_VERSION >= 0x01000102 ++ rc = libusb_get_port_numbers(dev, path, 7); ++#else + rc = libusb_get_port_path(ctx, dev, path, 7); ++#endif + if (rc < 0) { + return 0; + } diff --git a/SOURCES/kvm-usb-host-libusb-Fix-reset-handling.patch b/SOURCES/kvm-usb-host-libusb-Fix-reset-handling.patch new file mode 100644 index 0000000..827b9c8 --- /dev/null +++ b/SOURCES/kvm-usb-host-libusb-Fix-reset-handling.patch @@ -0,0 +1,75 @@ +From d8c698663916222fea36f660f0e56a23a8688afc Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 6 Nov 2013 12:16:58 +0100 +Subject: [PATCH 63/81] usb-host-libusb: Fix reset handling + +RH-Author: Gerd Hoffmann +Message-id: <1383740220-2049-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 55513 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/3] usb-host-libusb: Fix reset handling +Bugzilla: 980415 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Alex Williamson + +From: Hans de Goede + +The guest will issue an initial device reset when the device is attached, but +since the current usb-host-libusb code only actually does the reset when +udev->configuration != 0, and on attach the device is not yet configured, +the reset gets ignored. This means that the device gets passed to the guest +in an unknown state, which is not good. + +The udev->configuration check is there because of the release / claim +interfaces done around the libusb_device_reset call, but these are not +necessary. If interfaces are claimed when libusb_device_reset gets called +libusb will release + reclaim them itself. + +The usb_host_ep_update call also is not necessary. If the reset succeeds the +original config and interface alt settings will be restored. + +Last if the reset fails, that means the device has either disconnected or +morphed into an another device and has been completely re-enumerated, +so it is treated by the host as a new device and our handle is invalid, +so on reset failure we need to call usb_host_nodev(). + +Signed-off-by: Hans de Goede +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 5af35d7feccaa7d26b72c6c3d14116421d736b36) +--- + hw/usb/host-libusb.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/host-libusb.c | 10 ++++------ + 1 files changed, 4 insertions(+), 6 deletions(-) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index f660770..9c8905e 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1256,16 +1256,14 @@ static void usb_host_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) + static void usb_host_handle_reset(USBDevice *udev) + { + USBHostDevice *s = USB_HOST_DEVICE(udev); ++ int rc; + + trace_usb_host_reset(s->bus_num, s->addr); + +- if (udev->configuration == 0) { +- return; ++ rc = libusb_reset_device(s->dh); ++ if (rc != 0) { ++ usb_host_nodev(s); + } +- usb_host_release_interfaces(s); +- libusb_reset_device(s->dh); +- usb_host_claim_interfaces(s, 0); +- usb_host_ep_update(s); + } + + /* +-- +1.7.1 + diff --git a/SOURCES/kvm-usb-remove-old-usb-host-code.patch b/SOURCES/kvm-usb-remove-old-usb-host-code.patch new file mode 100644 index 0000000..8ab4201 --- /dev/null +++ b/SOURCES/kvm-usb-remove-old-usb-host-code.patch @@ -0,0 +1,2665 @@ +From 328574a81c4879246b3f222447654eced05ab570 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 5 Nov 2013 10:54:20 +0100 +Subject: [PATCH 14/29] usb: remove old usb-host code + +RH-Author: Gerd Hoffmann +Message-id: <1383648860-6526-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 55374 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] usb: remove old usb-host code +Bugzilla: 1001144 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +The usb-host code has been rewritten for qemu 1.5 to use libusb, +the old code has been left in as temporary fallback. Now we are +two releases further out, targeting the 1.7 release. No major +issues with the new code poped up until now. Time to remove it +from tre tree. Should we ever need it again for some reason -- +git has a copy for us in the history. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit b5613fdcb0e03d47852582c252942512f050b5b6) + +Conflicts: + configure + hw/usb/host-linux.c +--- + configure | 24 +- + hw/usb/host-bsd.c | 639 ----------------- + hw/usb/host-linux.c | 1910 --------------------------------------------------- + 3 files changed, 4 insertions(+), 2569 deletions(-) + delete mode 100644 hw/usb/host-bsd.c + delete mode 100644 hw/usb/host-linux.c + +Signed-off-by: Miroslav Rezanina +--- + configure | 24 +- + hw/usb/host-bsd.c | 639 ----------------- + hw/usb/host-linux.c | 1910 --------------------------------------------------- + 3 files changed, 4 insertions(+), 2569 deletions(-) + delete mode 100644 hw/usb/host-bsd.c + delete mode 100644 hw/usb/host-linux.c + +diff --git a/configure b/configure +index df587d7..4830f7e 100755 +--- a/configure ++++ b/configure +@@ -538,7 +538,6 @@ Haiku) + audio_possible_drivers="oss alsa sdl esd pa" + linux="yes" + linux_user="yes" +- usb="linux" + kvm="yes" + vhost_net="yes" + vhost_scsi="yes" +@@ -551,7 +550,6 @@ esac + + if [ "$bsd" = "yes" ] ; then + if [ "$darwin" != "yes" ] ; then +- usb="bsd" + bsd_user="yes" + fi + fi +@@ -3036,7 +3034,6 @@ fi + if test "$libusb" != "no" ; then + if $pkg_config --atleast-version=1.0.13 libusb-1.0 >/dev/null 2>&1 ; then + libusb="yes" +- usb="libusb" + libusb_cflags=$($pkg_config --cflags libusb-1.0 2>/dev/null) + libusb_libs=$($pkg_config --libs libusb-1.0 2>/dev/null) + QEMU_CFLAGS="$QEMU_CFLAGS $libusb_cflags" +@@ -3944,24 +3941,11 @@ if test "$virtio_blk_data_plane" = "yes" ; then + fi + + # USB host support +-case "$usb" in +-linux) +- echo "HOST_USB=linux legacy" >> $config_host_mak +-;; +-bsd) +- echo "HOST_USB=bsd" >> $config_host_mak +-;; +-libusb) +- if test "$linux" = "yes"; then +- echo "HOST_USB=libusb linux legacy" >> $config_host_mak +- else +- echo "HOST_USB=libusb legacy" >> $config_host_mak +- fi +-;; +-*) ++if test "$libusb" = "yes"; then ++ echo "HOST_USB=libusb legacy" >> $config_host_mak ++else + echo "HOST_USB=stub" >> $config_host_mak +-;; +-esac ++fi + + # TPM passthrough support? + if test "$tpm" = "yes"; then +diff --git a/hw/usb/host-bsd.c b/hw/usb/host-bsd.c +deleted file mode 100644 +index 39f2281..0000000 +--- a/hw/usb/host-bsd.c ++++ /dev/null +@@ -1,639 +0,0 @@ +-/* +- * BSD host USB redirector +- * +- * Copyright (c) 2006 Lonnie Mendez +- * Portions of code and concepts borrowed from +- * usb-linux.c and libusb's bsd.c and are copyright their respective owners. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a copy +- * of this software and associated documentation files (the "Software"), to deal +- * in the Software without restriction, including without limitation the rights +- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +- * copies of the Software, and to permit persons to whom the Software is +- * furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +- * THE SOFTWARE. +- */ +- +-#include "qemu-common.h" +-#include "monitor/monitor.h" +-#include "hw/usb.h" +- +-/* usb.h declares these */ +-#undef USB_SPEED_HIGH +-#undef USB_SPEED_FULL +-#undef USB_SPEED_LOW +- +-#include +-#ifndef __DragonFly__ +-#include +-#else +-#include +-#endif +- +-/* This value has maximum potential at 16. +- * You should also set hw.usb.debug to gain +- * more detailed view. +- */ +-//#define DEBUG +-#define UGEN_DEBUG_LEVEL 0 +- +- +-typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, +- int vendor_id, int product_id, +- const char *product_name, int speed); +-static int usb_host_find_device(int *pbus_num, int *paddr, +- const char *devname); +- +-typedef struct USBHostDevice { +- USBDevice dev; +- int ep_fd[USB_MAX_ENDPOINTS]; +- int devfd; +- char devpath[32]; +-} USBHostDevice; +- +- +-static int ensure_ep_open(USBHostDevice *dev, int ep, int mode) +-{ +- char buf[32]; +- int fd; +- +- /* Get the address for this endpoint */ +- ep = UE_GET_ADDR(ep); +- +- if (dev->ep_fd[ep] < 0) { +-#if defined(__FreeBSD__) || defined(__DragonFly__) +- snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep); +-#else +- snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep); +-#endif +- /* Try to open it O_RDWR first for those devices which have in and out +- * endpoints with the same address (eg 0x02 and 0x82) +- */ +- fd = open(buf, O_RDWR); +- if (fd < 0 && errno == ENXIO) +- fd = open(buf, mode); +- if (fd < 0) { +-#ifdef DEBUG +- printf("ensure_ep_open: failed to open device endpoint %s: %s\n", +- buf, strerror(errno)); +-#endif +- } +- dev->ep_fd[ep] = fd; +- } +- +- return dev->ep_fd[ep]; +-} +- +-static void ensure_eps_closed(USBHostDevice *dev) +-{ +- int epnum = 1; +- +- if (!dev) +- return; +- +- while (epnum < USB_MAX_ENDPOINTS) { +- if (dev->ep_fd[epnum] >= 0) { +- close(dev->ep_fd[epnum]); +- dev->ep_fd[epnum] = -1; +- } +- epnum++; +- } +-} +- +-static void usb_host_handle_reset(USBDevice *dev) +-{ +-#if 0 +- USBHostDevice *s = (USBHostDevice *)dev; +-#endif +-} +- +-/* XXX: +- * -check device states against transfer requests +- * and return appropriate response +- */ +-static void usb_host_handle_control(USBDevice *dev, +- USBPacket *p, +- int request, +- int value, +- int index, +- int length, +- uint8_t *data) +-{ +- USBHostDevice *s = (USBHostDevice *)dev; +- struct usb_ctl_request req; +- struct usb_alt_interface aiface; +- int ret, timeout = 50; +- +- if ((request >> 8) == UT_WRITE_DEVICE && +- (request & 0xff) == UR_SET_ADDRESS) { +- +- /* specific SET_ADDRESS support */ +- dev->addr = value; +- } else if ((request >> 8) == UT_WRITE_DEVICE && +- (request & 0xff) == UR_SET_CONFIG) { +- +- ensure_eps_closed(s); /* can't do this without all eps closed */ +- +- ret = ioctl(s->devfd, USB_SET_CONFIG, &value); +- if (ret < 0) { +-#ifdef DEBUG +- printf("handle_control: failed to set configuration - %s\n", +- strerror(errno)); +-#endif +- p->status = USB_RET_STALL; +- } +- } else if ((request >> 8) == UT_WRITE_INTERFACE && +- (request & 0xff) == UR_SET_INTERFACE) { +- +- aiface.uai_interface_index = index; +- aiface.uai_alt_no = value; +- +- ensure_eps_closed(s); /* can't do this without all eps closed */ +- ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface); +- if (ret < 0) { +-#ifdef DEBUG +- printf("handle_control: failed to set alternate interface - %s\n", +- strerror(errno)); +-#endif +- p->status = USB_RET_STALL; +- } +- } else { +- req.ucr_request.bmRequestType = request >> 8; +- req.ucr_request.bRequest = request & 0xff; +- USETW(req.ucr_request.wValue, value); +- USETW(req.ucr_request.wIndex, index); +- USETW(req.ucr_request.wLength, length); +- req.ucr_data = data; +- req.ucr_flags = USBD_SHORT_XFER_OK; +- +- ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout); +-#if defined(__NetBSD__) || defined(__OpenBSD__) +- if (ret < 0 && errno != EINVAL) { +-#else +- if (ret < 0) { +-#endif +-#ifdef DEBUG +- printf("handle_control: setting timeout failed - %s\n", +- strerror(errno)); +-#endif +- } +- +- ret = ioctl(s->devfd, USB_DO_REQUEST, &req); +- /* ugen returns EIO for usbd_do_request_ no matter what +- * happens with the transfer */ +- if (ret < 0) { +-#ifdef DEBUG +- printf("handle_control: error after request - %s\n", +- strerror(errno)); +-#endif +- p->status = USB_RET_NAK; /* STALL */ +- } else { +- p->actual_length = req.ucr_actlen; +- } +- } +-} +- +-static void usb_host_handle_data(USBDevice *dev, USBPacket *p) +-{ +- USBHostDevice *s = (USBHostDevice *)dev; +- int ret, fd, mode; +- int one = 1, shortpacket = 0, timeout = 50; +- sigset_t new_mask, old_mask; +- uint8_t devep = p->ep->nr; +- +- /* protect data transfers from SIGALRM signal */ +- sigemptyset(&new_mask); +- sigaddset(&new_mask, SIGALRM); +- sigprocmask(SIG_BLOCK, &new_mask, &old_mask); +- +- if (p->pid == USB_TOKEN_IN) { +- devep |= 0x80; +- mode = O_RDONLY; +- shortpacket = 1; +- } else { +- mode = O_WRONLY; +- } +- +- fd = ensure_ep_open(s, devep, mode); +- if (fd < 0) { +- sigprocmask(SIG_SETMASK, &old_mask, NULL); +- p->status = USB_RET_NODEV; +- return; +- } +- +- if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) { +-#ifdef DEBUG +- printf("handle_data: failed to set timeout - %s\n", +- strerror(errno)); +-#endif +- } +- +- if (shortpacket) { +- if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) { +-#ifdef DEBUG +- printf("handle_data: failed to set short xfer mode - %s\n", +- strerror(errno)); +-#endif +- sigprocmask(SIG_SETMASK, &old_mask, NULL); +- } +- } +- +- if (p->pid == USB_TOKEN_IN) +- ret = readv(fd, p->iov.iov, p->iov.niov); +- else +- ret = writev(fd, p->iov.iov, p->iov.niov); +- +- sigprocmask(SIG_SETMASK, &old_mask, NULL); +- +- if (ret < 0) { +-#ifdef DEBUG +- printf("handle_data: error after %s data - %s\n", +- pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno)); +-#endif +- switch(errno) { +- case ETIMEDOUT: +- case EINTR: +- p->status = USB_RET_NAK; +- break; +- default: +- p->status = USB_RET_STALL; +- } +- } else { +- p->actual_length = ret; +- } +-} +- +-static void usb_host_handle_destroy(USBDevice *opaque) +-{ +- USBHostDevice *s = (USBHostDevice *)opaque; +- int i; +- +- for (i = 0; i < USB_MAX_ENDPOINTS; i++) +- if (s->ep_fd[i] >= 0) +- close(s->ep_fd[i]); +- +- if (s->devfd < 0) +- return; +- +- close(s->devfd); +- +- g_free(s); +-} +- +-static int usb_host_initfn(USBDevice *dev) +-{ +- dev->flags |= (1 << USB_DEV_FLAG_IS_HOST); +- return 0; +-} +- +-USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname) +-{ +- struct usb_device_info bus_info, dev_info; +- USBDevice *d = NULL, *ret = NULL; +- USBHostDevice *dev; +- char ctlpath[PATH_MAX + 1]; +- char buspath[PATH_MAX + 1]; +- int bfd, dfd, bus, address, i; +- int ugendebug = UGEN_DEBUG_LEVEL; +- +- if (usb_host_find_device(&bus, &address, devname) < 0) { +- goto fail; +- } +- +- snprintf(buspath, PATH_MAX, "/dev/usb%d", bus); +- +- bfd = open(buspath, O_RDWR); +- if (bfd < 0) { +-#ifdef DEBUG +- printf("usb_host_device_open: failed to open usb bus - %s\n", +- strerror(errno)); +-#endif +- goto fail; +- } +- +- bus_info.udi_addr = address; +- if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) { +-#ifdef DEBUG +- printf("usb_host_device_open: failed to grab bus information - %s\n", +- strerror(errno)); +-#endif +- goto fail_bfd; +- } +- +-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +- snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]); +-#else +- snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]); +-#endif +- +- dfd = open(ctlpath, O_RDWR); +- if (dfd < 0) { +- dfd = open(ctlpath, O_RDONLY); +- if (dfd < 0) { +-#ifdef DEBUG +- printf("usb_host_device_open: failed to open usb device %s - %s\n", +- ctlpath, strerror(errno)); +-#endif +- } +- goto fail_dfd; +- } +- +- if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) { +-#ifdef DEBUG +- printf("usb_host_device_open: failed to grab device info - %s\n", +- strerror(errno)); +-#endif +- goto fail_dfd; +- } +- +- d = usb_create(guest_bus, "usb-host"); +- dev = DO_UPCAST(USBHostDevice, dev, d); +- +- if (dev_info.udi_speed == 1) { +- dev->dev.speed = USB_SPEED_LOW - 1; +- dev->dev.speedmask = USB_SPEED_MASK_LOW; +- } else { +- dev->dev.speed = USB_SPEED_FULL - 1; +- dev->dev.speedmask = USB_SPEED_MASK_FULL; +- } +- +- if (strncmp(dev_info.udi_product, "product", 7) != 0) { +- pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc), +- dev_info.udi_product); +- } else { +- snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc), +- "host:%s", devname); +- } +- +- pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/"); +- pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]); +- +- /* Mark the endpoints as not yet open */ +- for (i = 0; i < USB_MAX_ENDPOINTS; i++) { +- dev->ep_fd[i] = -1; +- } +- +- ioctl(dfd, USB_SETDEBUG, &ugendebug); +- +- ret = (USBDevice *)dev; +- +-fail_dfd: +- close(dfd); +-fail_bfd: +- close(bfd); +-fail: +- return ret; +-} +- +-static void usb_host_class_initfn(ObjectClass *klass, void *data) +-{ +- USBDeviceClass *uc = USB_DEVICE_CLASS(klass); +- +- uc->product_desc = "USB Host Device"; +- uc->init = usb_host_initfn; +- uc->handle_reset = usb_host_handle_reset; +- uc->handle_control = usb_host_handle_control; +- uc->handle_data = usb_host_handle_data; +- uc->handle_destroy = usb_host_handle_destroy; +-} +- +-static const TypeInfo usb_host_dev_info = { +- .name = "usb-host", +- .parent = TYPE_USB_DEVICE, +- .instance_size = sizeof(USBHostDevice), +- .class_init = usb_host_class_initfn, +-}; +- +-static void usb_host_register_types(void) +-{ +- type_register_static(&usb_host_dev_info); +-} +- +-type_init(usb_host_register_types) +- +-static int usb_host_scan(void *opaque, USBScanFunc *func) +-{ +- struct usb_device_info bus_info; +- struct usb_device_info dev_info; +- uint16_t vendor_id, product_id, class_id, speed; +- int bfd, dfd, bus, address; +- char busbuf[20], devbuf[20], product_name[256]; +- int ret = 0; +- +- for (bus = 0; bus < 10; bus++) { +- +- snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus); +- bfd = open(busbuf, O_RDWR); +- if (bfd < 0) +- continue; +- +- for (address = 1; address < 127; address++) { +- +- bus_info.udi_addr = address; +- if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) +- continue; +- +- /* only list devices that can be used by generic layer */ +- if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0) +- continue; +- +-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +- snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]); +-#else +- snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]); +-#endif +- +- dfd = open(devbuf, O_RDONLY); +- if (dfd < 0) { +-#ifdef DEBUG +- printf("usb_host_scan: couldn't open device %s - %s\n", devbuf, +- strerror(errno)); +-#endif +- continue; +- } +- +- if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) +- printf("usb_host_scan: couldn't get device information for %s - %s\n", +- devbuf, strerror(errno)); +- +- /* XXX: might need to fixup endianness of word values before copying over */ +- +- vendor_id = dev_info.udi_vendorNo; +- product_id = dev_info.udi_productNo; +- class_id = dev_info.udi_class; +- speed = dev_info.udi_speed; +- +- if (strncmp(dev_info.udi_product, "product", 7) != 0) +- pstrcpy(product_name, sizeof(product_name), +- dev_info.udi_product); +- else +- product_name[0] = '\0'; +- +- ret = func(opaque, bus, address, class_id, vendor_id, +- product_id, product_name, speed); +- +- close(dfd); +- +- if (ret) +- goto the_end; +- } +- +- close(bfd); +- } +- +-the_end: +- return ret; +-} +- +-typedef struct FindDeviceState { +- int vendor_id; +- int product_id; +- int bus_num; +- int addr; +-} FindDeviceState; +- +-static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, +- int class_id, +- int vendor_id, int product_id, +- const char *product_name, int speed) +-{ +- FindDeviceState *s = opaque; +- if (vendor_id == s->vendor_id && +- product_id == s->product_id) { +- s->bus_num = bus_num; +- s->addr = addr; +- return 1; +- } else { +- return 0; +- } +-} +- +- +-/* the syntax is : +- 'bus.addr' (decimal numbers) or +- 'vendor_id:product_id' (hexa numbers) */ +-static int usb_host_find_device(int *pbus_num, int *paddr, +- const char *devname) +-{ +- const char *p; +- int ret; +- FindDeviceState fs; +- +- p = strchr(devname, '.'); +- if (p) { +- *pbus_num = strtoul(devname, NULL, 0); +- *paddr = strtoul(p + 1, NULL, 0); +- return 0; +- } +- p = strchr(devname, ':'); +- if (p) { +- fs.vendor_id = strtoul(devname, NULL, 16); +- fs.product_id = strtoul(p + 1, NULL, 16); +- ret = usb_host_scan(&fs, usb_host_find_device_scan); +- if (ret) { +- *pbus_num = fs.bus_num; +- *paddr = fs.addr; +- return 0; +- } +- } +- return -1; +-} +- +-/**********************/ +-/* USB host device info */ +- +-struct usb_class_info { +- int class; +- const char *class_name; +-}; +- +-static const struct usb_class_info usb_class_info[] = { +- { USB_CLASS_AUDIO, "Audio"}, +- { USB_CLASS_COMM, "Communication"}, +- { USB_CLASS_HID, "HID"}, +- { USB_CLASS_HUB, "Hub" }, +- { USB_CLASS_PHYSICAL, "Physical" }, +- { USB_CLASS_PRINTER, "Printer" }, +- { USB_CLASS_MASS_STORAGE, "Storage" }, +- { USB_CLASS_CDC_DATA, "Data" }, +- { USB_CLASS_APP_SPEC, "Application Specific" }, +- { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, +- { USB_CLASS_STILL_IMAGE, "Still Image" }, +- { USB_CLASS_CSCID, "Smart Card" }, +- { USB_CLASS_CONTENT_SEC, "Content Security" }, +- { -1, NULL } +-}; +- +-static const char *usb_class_str(uint8_t class) +-{ +- const struct usb_class_info *p; +- for (p = usb_class_info; p->class != -1; p++) { +- if (p->class == class) +- break; +- } +- return p->class_name; +-} +- +-static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id, +- int vendor_id, int product_id, +- const char *product_name, +- int speed) +-{ +- const char *class_str, *speed_str; +- +- switch(speed) { +- case USB_SPEED_LOW: +- speed_str = "1.5"; +- break; +- case USB_SPEED_FULL: +- speed_str = "12"; +- break; +- case USB_SPEED_HIGH: +- speed_str = "480"; +- break; +- default: +- speed_str = "?"; +- break; +- } +- +- monitor_printf(mon, " Device %d.%d, speed %s Mb/s\n", +- bus_num, addr, speed_str); +- class_str = usb_class_str(class_id); +- if (class_str) +- monitor_printf(mon, " %s:", class_str); +- else +- monitor_printf(mon, " Class %02x:", class_id); +- monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id); +- if (product_name[0] != '\0') +- monitor_printf(mon, ", %s", product_name); +- monitor_printf(mon, "\n"); +-} +- +-static int usb_host_info_device(void *opaque, +- int bus_num, int addr, +- int class_id, +- int vendor_id, int product_id, +- const char *product_name, +- int speed) +-{ +- Monitor *mon = opaque; +- +- usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id, +- product_name, speed); +- return 0; +-} +- +-void usb_host_info(Monitor *mon, const QDict *qdict) +-{ +- usb_host_scan(mon, usb_host_info_device); +-} +diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c +deleted file mode 100644 +index ca09a89..0000000 +--- a/hw/usb/host-linux.c ++++ /dev/null +@@ -1,1910 +0,0 @@ +-/* +- * Linux host USB redirector +- * +- * Copyright (c) 2005 Fabrice Bellard +- * +- * Copyright (c) 2008 Max Krasnyansky +- * Support for host device auto connect & disconnect +- * Major rewrite to support fully async operation +- * +- * Copyright 2008 TJ +- * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition +- * to the legacy /proc/bus/usb USB device discovery and handling +- * +- * Permission is hereby granted, free of charge, to any person obtaining a copy +- * of this software and associated documentation files (the "Software"), to deal +- * in the Software without restriction, including without limitation the rights +- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +- * copies of the Software, and to permit persons to whom the Software is +- * furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +- * THE SOFTWARE. +- */ +- +-#include "qemu-common.h" +-#include "qemu/timer.h" +-#include "monitor/monitor.h" +-#include "sysemu/sysemu.h" +-#include "trace.h" +- +-#include +-#include +- +-#include +-#include +-#include "hw/usb.h" +-#include "hw/usb/desc.h" +-#include "hw/usb/host.h" +- +-#ifdef CONFIG_USB_LIBUSB +-# define DEVNAME "usb-host-linux" +-#else +-# define DEVNAME "usb-host" +-#endif +- +-/* We redefine it to avoid version problems */ +-struct usb_ctrltransfer { +- uint8_t bRequestType; +- uint8_t bRequest; +- uint16_t wValue; +- uint16_t wIndex; +- uint16_t wLength; +- uint32_t timeout; +- void *data; +-}; +- +-typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port, +- int class_id, int vendor_id, int product_id, +- const char *product_name, int speed); +- +-//#define DEBUG +- +-#ifdef DEBUG +-#define DPRINTF printf +-#else +-#define DPRINTF(...) +-#endif +- +-#define PRODUCT_NAME_SZ 32 +-#define MAX_PORTLEN 16 +- +-/* endpoint association data */ +-#define ISO_FRAME_DESC_PER_URB 32 +- +-/* devio.c limits single requests to 16k */ +-#define MAX_USBFS_BUFFER_SIZE 16384 +- +-typedef struct AsyncURB AsyncURB; +- +-struct endp_data { +- uint8_t halted; +- uint8_t iso_started; +- AsyncURB *iso_urb; +- int iso_urb_idx; +- int iso_buffer_used; +- int inflight; +-}; +- +-enum USBHostDeviceOptions { +- USB_HOST_OPT_PIPELINE, +-}; +- +-typedef struct USBHostDevice { +- USBDevice dev; +- int fd; +- int hub_fd; +- int hub_port; +- +- uint8_t descr[8192]; +- int descr_len; +- int closing; +- uint32_t iso_urb_count; +- uint32_t options; +- Notifier exit; +- QEMUBH *bh; +- +- struct endp_data ep_in[USB_MAX_ENDPOINTS]; +- struct endp_data ep_out[USB_MAX_ENDPOINTS]; +- QLIST_HEAD(, AsyncURB) aurbs; +- +- /* Host side address */ +- int bus_num; +- int addr; +- char port[MAX_PORTLEN]; +- struct USBAutoFilter match; +- int32_t bootindex; +- int seen, errcount; +- +- QTAILQ_ENTRY(USBHostDevice) next; +-} USBHostDevice; +- +-static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs); +- +-static int usb_host_close(USBHostDevice *dev); +-static void usb_host_auto_check(void *unused); +-static int usb_host_read_file(char *line, size_t line_size, +- const char *device_file, const char *device_name); +-static void usb_linux_update_endp_table(USBHostDevice *s); +- +-static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p) +-{ +- static const int usbfs[] = { +- [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL, +- [USB_ENDPOINT_XFER_ISOC] = USBDEVFS_URB_TYPE_ISO, +- [USB_ENDPOINT_XFER_BULK] = USBDEVFS_URB_TYPE_BULK, +- [USB_ENDPOINT_XFER_INT] = USBDEVFS_URB_TYPE_INTERRUPT, +- }; +- uint8_t type = p->ep->type; +- assert(type < ARRAY_SIZE(usbfs)); +- return usbfs[type]; +-} +- +-static int usb_host_do_reset(USBHostDevice *dev) +-{ +- struct timeval s, e; +- uint32_t usecs; +- int ret; +- +- gettimeofday(&s, NULL); +- ret = ioctl(dev->fd, USBDEVFS_RESET); +- gettimeofday(&e, NULL); +- usecs = (e.tv_sec - s.tv_sec) * 1000000; +- usecs += e.tv_usec - s.tv_usec; +- if (usecs > 1000000) { +- /* more than a second, something is fishy, broken usb device? */ +- fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n", +- dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000); +- } +- return ret; +-} +- +-static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep) +-{ +- struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out; +- assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT); +- assert(ep > 0 && ep <= USB_MAX_ENDPOINTS); +- return eps + ep - 1; +-} +- +-static int is_isoc(USBHostDevice *s, int pid, int ep) +-{ +- return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC; +-} +- +-static int is_valid(USBHostDevice *s, int pid, int ep) +-{ +- return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID; +-} +- +-static int is_halted(USBHostDevice *s, int pid, int ep) +-{ +- return get_endp(s, pid, ep)->halted; +-} +- +-static void clear_halt(USBHostDevice *s, int pid, int ep) +-{ +- trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep); +- get_endp(s, pid, ep)->halted = 0; +-} +- +-static void set_halt(USBHostDevice *s, int pid, int ep) +-{ +- if (ep != 0) { +- trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep); +- get_endp(s, pid, ep)->halted = 1; +- } +-} +- +-static int is_iso_started(USBHostDevice *s, int pid, int ep) +-{ +- return get_endp(s, pid, ep)->iso_started; +-} +- +-static void clear_iso_started(USBHostDevice *s, int pid, int ep) +-{ +- trace_usb_host_iso_stop(s->bus_num, s->addr, ep); +- get_endp(s, pid, ep)->iso_started = 0; +-} +- +-static void set_iso_started(USBHostDevice *s, int pid, int ep) +-{ +- struct endp_data *e = get_endp(s, pid, ep); +- +- trace_usb_host_iso_start(s->bus_num, s->addr, ep); +- if (!e->iso_started) { +- e->iso_started = 1; +- e->inflight = 0; +- } +-} +- +-static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value) +-{ +- struct endp_data *e = get_endp(s, pid, ep); +- +- e->inflight += value; +- return e->inflight; +-} +- +-static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb) +-{ +- get_endp(s, pid, ep)->iso_urb = iso_urb; +-} +- +-static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep) +-{ +- return get_endp(s, pid, ep)->iso_urb; +-} +- +-static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i) +-{ +- get_endp(s, pid, ep)->iso_urb_idx = i; +-} +- +-static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep) +-{ +- return get_endp(s, pid, ep)->iso_urb_idx; +-} +- +-static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i) +-{ +- get_endp(s, pid, ep)->iso_buffer_used = i; +-} +- +-static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep) +-{ +- return get_endp(s, pid, ep)->iso_buffer_used; +-} +- +-/* +- * Async URB state. +- * We always allocate iso packet descriptors even for bulk transfers +- * to simplify allocation and casts. +- */ +-struct AsyncURB +-{ +- struct usbdevfs_urb urb; +- struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB]; +- USBHostDevice *hdev; +- QLIST_ENTRY(AsyncURB) next; +- +- /* For regular async urbs */ +- USBPacket *packet; +- int more; /* large transfer, more urbs follow */ +- +- /* For buffered iso handling */ +- int iso_frame_idx; /* -1 means in flight */ +-}; +- +-static AsyncURB *async_alloc(USBHostDevice *s) +-{ +- AsyncURB *aurb = g_malloc0(sizeof(AsyncURB)); +- aurb->hdev = s; +- QLIST_INSERT_HEAD(&s->aurbs, aurb, next); +- return aurb; +-} +- +-static void async_free(AsyncURB *aurb) +-{ +- QLIST_REMOVE(aurb, next); +- g_free(aurb); +-} +- +-static void do_disconnect(USBHostDevice *s) +-{ +- usb_host_close(s); +- usb_host_auto_check(NULL); +-} +- +-static void async_complete(void *opaque) +-{ +- USBHostDevice *s = opaque; +- AsyncURB *aurb; +- int urbs = 0; +- +- while (1) { +- USBPacket *p; +- +- int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb); +- if (r < 0) { +- if (errno == EAGAIN) { +- if (urbs > 2) { +- /* indicates possible latency issues */ +- trace_usb_host_iso_many_urbs(s->bus_num, s->addr, urbs); +- } +- return; +- } +- if (errno == ENODEV) { +- if (!s->closing) { +- trace_usb_host_disconnect(s->bus_num, s->addr); +- do_disconnect(s); +- } +- return; +- } +- +- perror("USBDEVFS_REAPURBNDELAY"); +- return; +- } +- +- DPRINTF("husb: async completed. aurb %p status %d alen %d\n", +- aurb, aurb->urb.status, aurb->urb.actual_length); +- +- /* If this is a buffered iso urb mark it as complete and don't do +- anything else (it is handled further in usb_host_handle_iso_data) */ +- if (aurb->iso_frame_idx == -1) { +- int inflight; +- int pid = (aurb->urb.endpoint & USB_DIR_IN) ? +- USB_TOKEN_IN : USB_TOKEN_OUT; +- int ep = aurb->urb.endpoint & 0xf; +- if (aurb->urb.status == -EPIPE) { +- set_halt(s, pid, ep); +- } +- aurb->iso_frame_idx = 0; +- urbs++; +- inflight = change_iso_inflight(s, pid, ep, -1); +- if (inflight == 0 && is_iso_started(s, pid, ep)) { +- /* can be latency issues, or simply end of stream */ +- trace_usb_host_iso_out_of_bufs(s->bus_num, s->addr, ep); +- } +- continue; +- } +- +- p = aurb->packet; +- trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status, +- aurb->urb.actual_length, aurb->more); +- +- if (p) { +- switch (aurb->urb.status) { +- case 0: +- p->actual_length += aurb->urb.actual_length; +- if (!aurb->more) { +- /* Clear previous ASYNC status */ +- p->status = USB_RET_SUCCESS; +- } +- break; +- +- case -EPIPE: +- set_halt(s, p->pid, p->ep->nr); +- p->status = USB_RET_STALL; +- break; +- +- case -EOVERFLOW: +- p->status = USB_RET_BABBLE; +- break; +- +- default: +- p->status = USB_RET_IOERROR; +- break; +- } +- +- if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) { +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, aurb->urb.actual_length); +- usb_generic_async_ctrl_complete(&s->dev, p); +- } else if (!aurb->more) { +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, aurb->urb.actual_length); +- usb_packet_complete(&s->dev, p); +- } +- } +- +- async_free(aurb); +- } +-} +- +-static void usb_host_async_cancel(USBDevice *dev, USBPacket *p) +-{ +- USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); +- AsyncURB *aurb; +- +- trace_usb_host_req_canceled(s->bus_num, s->addr, p); +- +- QLIST_FOREACH(aurb, &s->aurbs, next) { +- if (p != aurb->packet) { +- continue; +- } +- +- trace_usb_host_urb_canceled(s->bus_num, s->addr, aurb); +- +- /* Mark it as dead (see async_complete above) */ +- aurb->packet = NULL; +- +- int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb); +- if (r < 0) { +- DPRINTF("husb: async. discard urb failed errno %d\n", errno); +- } +- } +-} +- +-static int usb_host_open_device(int bus, int addr) +-{ +- const char *usbfs = NULL; +- char filename[32]; +- struct stat st; +- int fd, rc; +- +- rc = stat("/dev/bus/usb", &st); +- if (rc == 0 && S_ISDIR(st.st_mode)) { +- /* udev-created device nodes available */ +- usbfs = "/dev/bus/usb"; +- } else { +- /* fallback: usbfs mounted below /proc */ +- usbfs = "/proc/bus/usb"; +- } +- +- snprintf(filename, sizeof(filename), "%s/%03d/%03d", +- usbfs, bus, addr); +- fd = open(filename, O_RDWR | O_NONBLOCK); +- if (fd < 0) { +- fprintf(stderr, "husb: open %s: %s\n", filename, strerror(errno)); +- } +- return fd; +-} +- +-static int usb_host_claim_port(USBHostDevice *s) +-{ +-#ifdef USBDEVFS_CLAIM_PORT +- char *h, hub_name[64], line[1024]; +- int hub_addr, ret; +- +- snprintf(hub_name, sizeof(hub_name), "%d-%s", +- s->match.bus_num, s->match.port); +- +- /* try strip off last ".$portnr" to get hub */ +- h = strrchr(hub_name, '.'); +- if (h != NULL) { +- s->hub_port = atoi(h+1); +- *h = '\0'; +- } else { +- /* no dot in there -> it is the root hub */ +- snprintf(hub_name, sizeof(hub_name), "usb%d", +- s->match.bus_num); +- s->hub_port = atoi(s->match.port); +- } +- +- if (!usb_host_read_file(line, sizeof(line), "devnum", +- hub_name)) { +- return -1; +- } +- if (sscanf(line, "%d", &hub_addr) != 1) { +- return -1; +- } +- +- s->hub_fd = usb_host_open_device(s->match.bus_num, hub_addr); +- if (s->hub_fd < 0) { +- return -1; +- } +- +- ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port); +- if (ret < 0) { +- close(s->hub_fd); +- s->hub_fd = -1; +- return -1; +- } +- +- trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port); +- return 0; +-#else +- return -1; +-#endif +-} +- +-static void usb_host_release_port(USBHostDevice *s) +-{ +- if (s->hub_fd == -1) { +- return; +- } +-#ifdef USBDEVFS_RELEASE_PORT +- ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port); +-#endif +- close(s->hub_fd); +- s->hub_fd = -1; +-} +- +-static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces) +-{ +- /* earlier Linux 2.4 do not support that */ +-#ifdef USBDEVFS_DISCONNECT +- struct usbdevfs_ioctl ctrl; +- int ret, interface; +- +- for (interface = 0; interface < nb_interfaces; interface++) { +- ctrl.ioctl_code = USBDEVFS_DISCONNECT; +- ctrl.ifno = interface; +- ctrl.data = 0; +- ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl); +- if (ret < 0 && errno != ENODATA) { +- perror("USBDEVFS_DISCONNECT"); +- return -1; +- } +- } +-#endif +- return 0; +-} +- +-static int usb_linux_get_num_interfaces(USBHostDevice *s) +-{ +- char device_name[64], line[1024]; +- int num_interfaces = 0; +- +- sprintf(device_name, "%d-%s", s->bus_num, s->port); +- if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces", +- device_name)) { +- return -1; +- } +- if (sscanf(line, "%d", &num_interfaces) != 1) { +- return -1; +- } +- return num_interfaces; +-} +- +-static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) +-{ +- const char *op = NULL; +- int dev_descr_len, config_descr_len; +- int interface, nb_interfaces; +- int ret, i; +- +- for (i = 0; i < USB_MAX_INTERFACES; i++) { +- dev->dev.altsetting[i] = 0; +- } +- +- if (configuration == 0) { /* address state - ignore */ +- dev->dev.ninterfaces = 0; +- dev->dev.configuration = 0; +- return 1; +- } +- +- DPRINTF("husb: claiming interfaces. config %d\n", configuration); +- +- i = 0; +- dev_descr_len = dev->descr[0]; +- if (dev_descr_len > dev->descr_len) { +- fprintf(stderr, "husb: update iface failed. descr too short\n"); +- return 0; +- } +- +- i += dev_descr_len; +- while (i < dev->descr_len) { +- DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n", +- i, dev->descr_len, +- dev->descr[i], dev->descr[i+1]); +- +- if (dev->descr[i+1] != USB_DT_CONFIG) { +- i += dev->descr[i]; +- continue; +- } +- config_descr_len = dev->descr[i]; +- +- DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration); +- +- if (configuration == dev->descr[i + 5]) { +- configuration = dev->descr[i + 5]; +- break; +- } +- +- i += config_descr_len; +- } +- +- if (i >= dev->descr_len) { +- fprintf(stderr, +- "husb: update iface failed. no matching configuration\n"); +- return 0; +- } +- nb_interfaces = dev->descr[i + 4]; +- +- if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) { +- goto fail; +- } +- +- /* XXX: only grab if all interfaces are free */ +- for (interface = 0; interface < nb_interfaces; interface++) { +- op = "USBDEVFS_CLAIMINTERFACE"; +- ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface); +- if (ret < 0) { +- goto fail; +- } +- } +- +- trace_usb_host_claim_interfaces(dev->bus_num, dev->addr, +- nb_interfaces, configuration); +- +- dev->dev.ninterfaces = nb_interfaces; +- dev->dev.configuration = configuration; +- return 1; +- +-fail: +- if (errno == ENODEV) { +- do_disconnect(dev); +- } +- perror(op); +- return 0; +-} +- +-static int usb_host_release_interfaces(USBHostDevice *s) +-{ +- int ret, i; +- +- trace_usb_host_release_interfaces(s->bus_num, s->addr); +- +- for (i = 0; i < s->dev.ninterfaces; i++) { +- ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i); +- if (ret < 0) { +- perror("USBDEVFS_RELEASEINTERFACE"); +- return 0; +- } +- } +- return 1; +-} +- +-static void usb_host_handle_reset(USBDevice *dev) +-{ +- USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); +- +- trace_usb_host_reset(s->bus_num, s->addr); +- +- usb_host_do_reset(s); +- +- usb_host_claim_interfaces(s, 0); +- usb_linux_update_endp_table(s); +-} +- +-static void usb_host_handle_destroy(USBDevice *dev) +-{ +- USBHostDevice *s = (USBHostDevice *)dev; +- +- usb_host_release_port(s); +- usb_host_close(s); +- QTAILQ_REMOVE(&hostdevs, s, next); +- qemu_remove_exit_notifier(&s->exit); +-} +- +-/* iso data is special, we need to keep enough urbs in flight to make sure +- that the controller never runs out of them, otherwise the device will +- likely suffer a buffer underrun / overrun. */ +-static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep) +-{ +- AsyncURB *aurb; +- int i, j, len = usb_ep_get_max_packet_size(&s->dev, pid, ep); +- +- aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb)); +- for (i = 0; i < s->iso_urb_count; i++) { +- aurb[i].urb.endpoint = ep; +- aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len; +- aurb[i].urb.buffer = g_malloc(aurb[i].urb.buffer_length); +- aurb[i].urb.type = USBDEVFS_URB_TYPE_ISO; +- aurb[i].urb.flags = USBDEVFS_URB_ISO_ASAP; +- aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB; +- for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++) +- aurb[i].urb.iso_frame_desc[j].length = len; +- if (pid == USB_TOKEN_IN) { +- aurb[i].urb.endpoint |= 0x80; +- /* Mark as fully consumed (idle) */ +- aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB; +- } +- } +- set_iso_urb(s, pid, ep, aurb); +- +- return aurb; +-} +- +-static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep) +-{ +- AsyncURB *aurb; +- int i, ret, killed = 0, free = 1; +- +- aurb = get_iso_urb(s, pid, ep); +- if (!aurb) { +- return; +- } +- +- for (i = 0; i < s->iso_urb_count; i++) { +- /* in flight? */ +- if (aurb[i].iso_frame_idx == -1) { +- ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]); +- if (ret < 0) { +- perror("USBDEVFS_DISCARDURB"); +- free = 0; +- continue; +- } +- killed++; +- } +- } +- +- /* Make sure any urbs we've killed are reaped before we free them */ +- if (killed) { +- async_complete(s); +- } +- +- for (i = 0; i < s->iso_urb_count; i++) { +- g_free(aurb[i].urb.buffer); +- } +- +- if (free) +- g_free(aurb); +- else +- printf("husb: leaking iso urbs because of discard failure\n"); +- set_iso_urb(s, pid, ep, NULL); +- set_iso_urb_idx(s, pid, ep, 0); +- clear_iso_started(s, pid, ep); +-} +- +-static void urb_status_to_usb_ret(int status, USBPacket *p) +-{ +- switch (status) { +- case -EPIPE: +- p->status = USB_RET_STALL; +- break; +- case -EOVERFLOW: +- p->status = USB_RET_BABBLE; +- break; +- default: +- p->status = USB_RET_IOERROR; +- } +-} +- +-static void usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in) +-{ +- AsyncURB *aurb; +- int i, j, max_packet_size, offset, len; +- uint8_t *buf; +- +- max_packet_size = p->ep->max_packet_size; +- if (max_packet_size == 0) { +- p->status = USB_RET_NAK; +- return; +- } +- +- aurb = get_iso_urb(s, p->pid, p->ep->nr); +- if (!aurb) { +- aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr); +- } +- +- i = get_iso_urb_idx(s, p->pid, p->ep->nr); +- j = aurb[i].iso_frame_idx; +- if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) { +- if (in) { +- /* Check urb status */ +- if (aurb[i].urb.status) { +- urb_status_to_usb_ret(aurb[i].urb.status, p); +- /* Move to the next urb */ +- aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1; +- /* Check frame status */ +- } else if (aurb[i].urb.iso_frame_desc[j].status) { +- urb_status_to_usb_ret(aurb[i].urb.iso_frame_desc[j].status, p); +- /* Check the frame fits */ +- } else if (aurb[i].urb.iso_frame_desc[j].actual_length +- > p->iov.size) { +- printf("husb: received iso data is larger then packet\n"); +- p->status = USB_RET_BABBLE; +- /* All good copy data over */ +- } else { +- len = aurb[i].urb.iso_frame_desc[j].actual_length; +- buf = aurb[i].urb.buffer + +- j * aurb[i].urb.iso_frame_desc[0].length; +- usb_packet_copy(p, buf, len); +- } +- } else { +- len = p->iov.size; +- offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr); +- +- /* Check the frame fits */ +- if (len > max_packet_size) { +- printf("husb: send iso data is larger then max packet size\n"); +- p->status = USB_RET_NAK; +- return; +- } +- +- /* All good copy data over */ +- usb_packet_copy(p, aurb[i].urb.buffer + offset, len); +- aurb[i].urb.iso_frame_desc[j].length = len; +- offset += len; +- set_iso_buffer_used(s, p->pid, p->ep->nr, offset); +- +- /* Start the stream once we have buffered enough data */ +- if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) { +- set_iso_started(s, p->pid, p->ep->nr); +- } +- } +- aurb[i].iso_frame_idx++; +- if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) { +- i = (i + 1) % s->iso_urb_count; +- set_iso_urb_idx(s, p->pid, p->ep->nr, i); +- } +- } else { +- if (in) { +- set_iso_started(s, p->pid, p->ep->nr); +- } else { +- DPRINTF("hubs: iso out error no free buffer, dropping packet\n"); +- } +- } +- +- if (is_iso_started(s, p->pid, p->ep->nr)) { +- /* (Re)-submit all fully consumed / filled urbs */ +- for (i = 0; i < s->iso_urb_count; i++) { +- if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) { +- if (ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]) < 0) { +- perror("USBDEVFS_SUBMITURB"); +- if (!in || p->status == USB_RET_SUCCESS) { +- switch(errno) { +- case ETIMEDOUT: +- p->status = USB_RET_NAK; +- break; +- case EPIPE: +- default: +- p->status = USB_RET_STALL; +- } +- } +- break; +- } +- aurb[i].iso_frame_idx = -1; +- change_iso_inflight(s, p->pid, p->ep->nr, 1); +- } +- } +- } +-} +- +-static void usb_host_handle_data(USBDevice *dev, USBPacket *p) +-{ +- USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); +- struct usbdevfs_urb *urb; +- AsyncURB *aurb; +- int ret, rem, prem, v; +- uint8_t *pbuf; +- uint8_t ep; +- +- trace_usb_host_req_data(s->bus_num, s->addr, p, +- p->pid == USB_TOKEN_IN, +- p->ep->nr, p->iov.size); +- +- if (!is_valid(s, p->pid, p->ep->nr)) { +- p->status = USB_RET_NAK; +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, p->actual_length); +- return; +- } +- +- if (p->pid == USB_TOKEN_IN) { +- ep = p->ep->nr | 0x80; +- } else { +- ep = p->ep->nr; +- } +- +- if (is_halted(s, p->pid, p->ep->nr)) { +- unsigned int arg = ep; +- ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg); +- if (ret < 0) { +- perror("USBDEVFS_CLEAR_HALT"); +- p->status = USB_RET_NAK; +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, p->actual_length); +- return; +- } +- clear_halt(s, p->pid, p->ep->nr); +- } +- +- if (is_isoc(s, p->pid, p->ep->nr)) { +- usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN); +- return; +- } +- +- v = 0; +- prem = 0; +- pbuf = NULL; +- rem = p->iov.size; +- do { +- if (prem == 0 && rem > 0) { +- assert(v < p->iov.niov); +- prem = p->iov.iov[v].iov_len; +- pbuf = p->iov.iov[v].iov_base; +- assert(prem <= rem); +- v++; +- } +- aurb = async_alloc(s); +- aurb->packet = p; +- +- urb = &aurb->urb; +- urb->endpoint = ep; +- urb->type = usb_host_usbfs_type(s, p); +- urb->usercontext = s; +- urb->buffer = pbuf; +- urb->buffer_length = prem; +- +- if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) { +- urb->buffer_length = MAX_USBFS_BUFFER_SIZE; +- } +- pbuf += urb->buffer_length; +- prem -= urb->buffer_length; +- rem -= urb->buffer_length; +- if (rem) { +- aurb->more = 1; +- } +- +- trace_usb_host_urb_submit(s->bus_num, s->addr, aurb, +- urb->buffer_length, aurb->more); +- ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb); +- +- DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n", +- urb->endpoint, urb->buffer_length, aurb->more, p, aurb); +- +- if (ret < 0) { +- perror("USBDEVFS_SUBMITURB"); +- async_free(aurb); +- +- switch(errno) { +- case ETIMEDOUT: +- p->status = USB_RET_NAK; +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, p->actual_length); +- break; +- case EPIPE: +- default: +- p->status = USB_RET_STALL; +- trace_usb_host_req_complete(s->bus_num, s->addr, p, +- p->status, p->actual_length); +- } +- return; +- } +- } while (rem > 0); +- +- p->status = USB_RET_ASYNC; +-} +- +-static int ctrl_error(void) +-{ +- if (errno == ETIMEDOUT) { +- return USB_RET_NAK; +- } else { +- return USB_RET_STALL; +- } +-} +- +-static void usb_host_set_address(USBHostDevice *s, int addr) +-{ +- trace_usb_host_set_address(s->bus_num, s->addr, addr); +- s->dev.addr = addr; +-} +- +-static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p) +-{ +- int ret, first = 1; +- +- trace_usb_host_set_config(s->bus_num, s->addr, config); +- +- usb_host_release_interfaces(s); +- +-again: +- ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config); +- +- DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno); +- +- if (ret < 0 && errno == EBUSY && first) { +- /* happens if usb device is in use by host drivers */ +- int count = usb_linux_get_num_interfaces(s); +- if (count > 0) { +- DPRINTF("husb: busy -> disconnecting %d interfaces\n", count); +- usb_host_disconnect_ifaces(s, count); +- first = 0; +- goto again; +- } +- } +- +- if (ret < 0) { +- p->status = ctrl_error(); +- return; +- } +- usb_host_claim_interfaces(s, config); +- usb_linux_update_endp_table(s); +-} +- +-static void usb_host_set_interface(USBHostDevice *s, int iface, int alt, +- USBPacket *p) +-{ +- struct usbdevfs_setinterface si; +- int i, ret; +- +- trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt); +- +- for (i = 1; i <= USB_MAX_ENDPOINTS; i++) { +- if (is_isoc(s, USB_TOKEN_IN, i)) { +- usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i); +- } +- if (is_isoc(s, USB_TOKEN_OUT, i)) { +- usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i); +- } +- } +- +- if (iface >= USB_MAX_INTERFACES) { +- p->status = USB_RET_STALL; +- return; +- } +- +- si.interface = iface; +- si.altsetting = alt; +- ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si); +- +- DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n", +- iface, alt, ret, errno); +- +- if (ret < 0) { +- p->status = ctrl_error(); +- return; +- } +- +- s->dev.altsetting[iface] = alt; +- usb_linux_update_endp_table(s); +-} +- +-static void usb_host_handle_control(USBDevice *dev, USBPacket *p, +- int request, int value, int index, int length, uint8_t *data) +-{ +- USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); +- struct usbdevfs_urb *urb; +- AsyncURB *aurb; +- int ret; +- +- /* +- * Process certain standard device requests. +- * These are infrequent and are processed synchronously. +- */ +- +- /* Note request is (bRequestType << 8) | bRequest */ +- trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); +- +- switch (request) { +- case DeviceOutRequest | USB_REQ_SET_ADDRESS: +- usb_host_set_address(s, value); +- trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); +- return; +- +- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: +- usb_host_set_config(s, value & 0xff, p); +- trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); +- return; +- +- case InterfaceOutRequest | USB_REQ_SET_INTERFACE: +- usb_host_set_interface(s, index, value, p); +- trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); +- return; +- +- case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: +- if (value == 0) { /* clear halt */ +- int pid = (index & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; +- ioctl(s->fd, USBDEVFS_CLEAR_HALT, &index); +- clear_halt(s, pid, index & 0x0f); +- trace_usb_host_req_emulated(s->bus_num, s->addr, p, 0); +- return; +- } +- } +- +- /* The rest are asynchronous */ +- if (length > sizeof(dev->data_buf)) { +- fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n", +- length, sizeof(dev->data_buf)); +- p->status = USB_RET_STALL; +- return; +- } +- +- aurb = async_alloc(s); +- aurb->packet = p; +- +- /* +- * Setup ctrl transfer. +- * +- * s->ctrl is laid out such that data buffer immediately follows +- * 'req' struct which is exactly what usbdevfs expects. +- */ +- urb = &aurb->urb; +- +- urb->type = USBDEVFS_URB_TYPE_CONTROL; +- urb->endpoint = p->ep->nr; +- +- urb->buffer = &dev->setup_buf; +- urb->buffer_length = length + 8; +- +- urb->usercontext = s; +- +- trace_usb_host_urb_submit(s->bus_num, s->addr, aurb, +- urb->buffer_length, aurb->more); +- ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb); +- +- DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb); +- +- if (ret < 0) { +- DPRINTF("husb: submit failed. errno %d\n", errno); +- async_free(aurb); +- +- switch(errno) { +- case ETIMEDOUT: +- p->status = USB_RET_NAK; +- break; +- case EPIPE: +- default: +- p->status = USB_RET_STALL; +- break; +- } +- return; +- } +- +- p->status = USB_RET_ASYNC; +-} +- +-static void usb_linux_update_endp_table(USBHostDevice *s) +-{ +- static const char *tname[] = { +- [USB_ENDPOINT_XFER_CONTROL] = "control", +- [USB_ENDPOINT_XFER_ISOC] = "isoc", +- [USB_ENDPOINT_XFER_BULK] = "bulk", +- [USB_ENDPOINT_XFER_INT] = "int", +- }; +- uint8_t devep, type; +- uint16_t mps, v, p; +- int ep, pid; +- unsigned int i, configuration = -1, interface = -1, altsetting = -1; +- struct endp_data *epd; +- USBDescriptor *d; +- bool active = false; +- +- usb_ep_reset(&s->dev); +- +- for (i = 0;; i += d->bLength) { +- if (i+2 >= s->descr_len) { +- break; +- } +- d = (void *)(s->descr + i); +- if (d->bLength < 2) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "descriptor too short"); +- return; +- } +- if (i + d->bLength > s->descr_len) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "descriptor too long"); +- return; +- } +- switch (d->bDescriptorType) { +- case 0: +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "invalid descriptor type"); +- return; +- case USB_DT_DEVICE: +- if (d->bLength < 0x12) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "device descriptor too short"); +- return; +- } +- v = (d->u.device.idVendor_hi << 8) | d->u.device.idVendor_lo; +- p = (d->u.device.idProduct_hi << 8) | d->u.device.idProduct_lo; +- trace_usb_host_parse_device(s->bus_num, s->addr, v, p); +- break; +- case USB_DT_CONFIG: +- if (d->bLength < 0x09) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "config descriptor too short"); +- return; +- } +- configuration = d->u.config.bConfigurationValue; +- active = (configuration == s->dev.configuration); +- trace_usb_host_parse_config(s->bus_num, s->addr, +- configuration, active); +- break; +- case USB_DT_INTERFACE: +- if (d->bLength < 0x09) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "interface descriptor too short"); +- return; +- } +- interface = d->u.interface.bInterfaceNumber; +- altsetting = d->u.interface.bAlternateSetting; +- active = (configuration == s->dev.configuration) && +- (altsetting == s->dev.altsetting[interface]); +- trace_usb_host_parse_interface(s->bus_num, s->addr, +- interface, altsetting, active); +- break; +- case USB_DT_ENDPOINT: +- if (d->bLength < 0x07) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "endpoint descriptor too short"); +- return; +- } +- devep = d->u.endpoint.bEndpointAddress; +- pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; +- ep = devep & 0xf; +- if (ep == 0) { +- trace_usb_host_parse_error(s->bus_num, s->addr, +- "invalid endpoint address"); +- return; +- } +- +- type = d->u.endpoint.bmAttributes & 0x3; +- mps = d->u.endpoint.wMaxPacketSize_lo | +- (d->u.endpoint.wMaxPacketSize_hi << 8); +- trace_usb_host_parse_endpoint(s->bus_num, s->addr, ep, +- (devep & USB_DIR_IN) ? "in" : "out", +- tname[type], active); +- +- if (active) { +- usb_ep_set_max_packet_size(&s->dev, pid, ep, mps); +- assert(usb_ep_get_type(&s->dev, pid, ep) == +- USB_ENDPOINT_XFER_INVALID); +- usb_ep_set_type(&s->dev, pid, ep, type); +- usb_ep_set_ifnum(&s->dev, pid, ep, interface); +- if ((s->options & (1 << USB_HOST_OPT_PIPELINE)) && +- (type == USB_ENDPOINT_XFER_BULK) && +- (pid == USB_TOKEN_OUT)) { +- usb_ep_set_pipeline(&s->dev, pid, ep, true); +- } +- +- epd = get_endp(s, pid, ep); +- epd->halted = 0; +- } +- +- break; +- default: +- trace_usb_host_parse_unknown(s->bus_num, s->addr, +- d->bLength, d->bDescriptorType); +- break; +- } +- } +-} +- +-/* +- * Check if we can safely redirect a usb2 device to a usb1 virtual controller, +- * this function assumes this is safe, if: +- * 1) There are no isoc endpoints +- * 2) There are no interrupt endpoints with a max_packet_size > 64 +- * Note bulk endpoints with a max_packet_size > 64 in theory also are not +- * usb1 compatible, but in practice this seems to work fine. +- */ +-static int usb_linux_full_speed_compat(USBHostDevice *dev) +-{ +- int i, packet_size; +- +- /* +- * usb_linux_update_endp_table only registers info about ep in the current +- * interface altsettings, so we need to parse the descriptors again. +- */ +- for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) { +- if (dev->descr[i + 1] == USB_DT_ENDPOINT) { +- switch (dev->descr[i + 3] & 0x3) { +- case 0x00: /* CONTROL */ +- break; +- case 0x01: /* ISO */ +- return 0; +- case 0x02: /* BULK */ +- break; +- case 0x03: /* INTERRUPT */ +- packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8); +- if (packet_size > 64) +- return 0; +- break; +- } +- } +- } +- return 1; +-} +- +-static int usb_host_open(USBHostDevice *dev, int bus_num, +- int addr, const char *port, +- const char *prod_name, int speed) +-{ +- int fd = -1, ret; +- +- trace_usb_host_open_started(bus_num, addr); +- +- if (dev->fd != -1) { +- goto fail; +- } +- +- fd = usb_host_open_device(bus_num, addr); +- if (fd < 0) { +- goto fail; +- } +- DPRINTF("husb: opened %s\n", buf); +- +- dev->bus_num = bus_num; +- dev->addr = addr; +- pstrcpy(dev->port, sizeof(dev->port), port); +- dev->fd = fd; +- +- /* read the device description */ +- dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); +- if (dev->descr_len <= 0) { +- perror("husb: reading device data failed"); +- goto fail; +- } +- +-#ifdef DEBUG +- { +- int x; +- printf("=== begin dumping device descriptor data ===\n"); +- for (x = 0; x < dev->descr_len; x++) { +- printf("%02x ", dev->descr[x]); +- } +- printf("\n=== end dumping device descriptor data ===\n"); +- } +-#endif +- +- +- /* start unconfigured -- we'll wait for the guest to set a configuration */ +- if (!usb_host_claim_interfaces(dev, 0)) { +- goto fail; +- } +- +- usb_ep_init(&dev->dev); +- usb_linux_update_endp_table(dev); +- +- if (speed == -1) { +- struct usbdevfs_connectinfo ci; +- +- ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); +- if (ret < 0) { +- perror("usb_host_device_open: USBDEVFS_CONNECTINFO"); +- goto fail; +- } +- +- if (ci.slow) { +- speed = USB_SPEED_LOW; +- } else { +- speed = USB_SPEED_HIGH; +- } +- } +- dev->dev.speed = speed; +- dev->dev.speedmask = (1 << speed); +- if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) { +- dev->dev.speedmask |= USB_SPEED_MASK_FULL; +- } +- +- trace_usb_host_open_success(bus_num, addr); +- +- if (!prod_name || prod_name[0] == '\0') { +- snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc), +- "host:%d.%d", bus_num, addr); +- } else { +- pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc), +- prod_name); +- } +- +- ret = usb_device_attach(&dev->dev); +- if (ret) { +- goto fail; +- } +- +- /* USB devio uses 'write' flag to check for async completions */ +- qemu_set_fd_handler(dev->fd, NULL, async_complete, dev); +- +- return 0; +- +-fail: +- trace_usb_host_open_failure(bus_num, addr); +- if (dev->fd != -1) { +- close(dev->fd); +- dev->fd = -1; +- } +- return -1; +-} +- +-static int usb_host_close(USBHostDevice *dev) +-{ +- int i; +- +- if (dev->fd == -1) { +- return -1; +- } +- +- trace_usb_host_close(dev->bus_num, dev->addr); +- +- qemu_set_fd_handler(dev->fd, NULL, NULL, NULL); +- dev->closing = 1; +- for (i = 1; i <= USB_MAX_ENDPOINTS; i++) { +- if (is_isoc(dev, USB_TOKEN_IN, i)) { +- usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i); +- } +- if (is_isoc(dev, USB_TOKEN_OUT, i)) { +- usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i); +- } +- } +- async_complete(dev); +- dev->closing = 0; +- if (dev->dev.attached) { +- usb_device_detach(&dev->dev); +- } +- usb_host_do_reset(dev); +- close(dev->fd); +- dev->fd = -1; +- return 0; +-} +- +-static void usb_host_exit_notifier(struct Notifier *n, void *data) +-{ +- USBHostDevice *s = container_of(n, USBHostDevice, exit); +- +- usb_host_release_port(s); +- if (s->fd != -1) { +- usb_host_do_reset(s); +- } +-} +- +-/* +- * This is *NOT* about restoring state. We have absolutely no idea +- * what state the host device is in at the moment and whenever it is +- * still present in the first place. Attemping to contine where we +- * left off is impossible. +- * +- * What we are going to to to here is emulate a surprise removal of +- * the usb device passed through, then kick host scan so the device +- * will get re-attached (and re-initialized by the guest) in case it +- * is still present. +- * +- * As the device removal will change the state of other devices (usb +- * host controller, most likely interrupt controller too) we have to +- * wait with it until *all* vmstate is loaded. Thus post_load just +- * kicks a bottom half which then does the actual work. +- */ +-static void usb_host_post_load_bh(void *opaque) +-{ +- USBHostDevice *dev = opaque; +- +- if (dev->fd != -1) { +- usb_host_close(dev); +- } +- if (dev->dev.attached) { +- usb_device_detach(&dev->dev); +- } +- usb_host_auto_check(NULL); +-} +- +-static int usb_host_post_load(void *opaque, int version_id) +-{ +- USBHostDevice *dev = opaque; +- +- qemu_bh_schedule(dev->bh); +- return 0; +-} +- +-static int usb_host_initfn(USBDevice *dev) +-{ +- USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); +- +- dev->flags |= (1 << USB_DEV_FLAG_IS_HOST); +- dev->auto_attach = 0; +- s->fd = -1; +- s->hub_fd = -1; +- +- QTAILQ_INSERT_TAIL(&hostdevs, s, next); +- s->exit.notify = usb_host_exit_notifier; +- qemu_add_exit_notifier(&s->exit); +- s->bh = qemu_bh_new(usb_host_post_load_bh, s); +- usb_host_auto_check(NULL); +- +- if (s->match.bus_num != 0 && s->match.port != NULL) { +- usb_host_claim_port(s); +- } +- add_boot_device_path(s->bootindex, &dev->qdev, NULL); +- return 0; +-} +- +-static const VMStateDescription vmstate_usb_host = { +- .name = DEVNAME, +- .version_id = 1, +- .minimum_version_id = 1, +- .post_load = usb_host_post_load, +- .fields = (VMStateField[]) { +- VMSTATE_USB_DEVICE(dev, USBHostDevice), +- VMSTATE_END_OF_LIST() +- } +-}; +- +-static Property usb_host_dev_properties[] = { +- DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), +- DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), +- DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), +- DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0), +- DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0), +- DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), +- DEFINE_PROP_INT32("bootindex", USBHostDevice, bootindex, -1), +- DEFINE_PROP_BIT("pipeline", USBHostDevice, options, +- USB_HOST_OPT_PIPELINE, true), +- DEFINE_PROP_END_OF_LIST(), +-}; +- +-static void usb_host_class_initfn(ObjectClass *klass, void *data) +-{ +- DeviceClass *dc = DEVICE_CLASS(klass); +- USBDeviceClass *uc = USB_DEVICE_CLASS(klass); +- +- uc->init = usb_host_initfn; +- uc->product_desc = "USB Host Device"; +- uc->cancel_packet = usb_host_async_cancel; +- uc->handle_data = usb_host_handle_data; +- uc->handle_control = usb_host_handle_control; +- uc->handle_reset = usb_host_handle_reset; +- uc->handle_destroy = usb_host_handle_destroy; +- dc->vmsd = &vmstate_usb_host; +- dc->props = usb_host_dev_properties; +-} +- +-static const TypeInfo usb_host_dev_info = { +- .name = DEVNAME, +- .parent = TYPE_USB_DEVICE, +- .instance_size = sizeof(USBHostDevice), +- .class_init = usb_host_class_initfn, +-}; +- +-static void usb_host_register_types(void) +-{ +- type_register_static(&usb_host_dev_info); +-} +- +-type_init(usb_host_register_types) +- +-/* +- * Read sys file-system device file +- * +- * @line address of buffer to put file contents in +- * @line_size size of line +- * @device_file path to device file (printf format string) +- * @device_name device being opened (inserted into device_file) +- * +- * @return 0 failed, 1 succeeded ('line' contains data) +- */ +-static int usb_host_read_file(char *line, size_t line_size, +- const char *device_file, const char *device_name) +-{ +- FILE *f; +- int ret = 0; +- char filename[PATH_MAX]; +- +- snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/%s", device_name, +- device_file); +- f = fopen(filename, "r"); +- if (f) { +- ret = fgets(line, line_size, f) != NULL; +- fclose(f); +- } +- +- return ret; +-} +- +-/* +- * Use /sys/bus/usb/devices/ directory to determine host's USB +- * devices. +- * +- * This code is based on Robert Schiele's original patches posted to +- * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950 +- */ +-static int usb_host_scan(void *opaque, USBScanFunc *func) +-{ +- DIR *dir = NULL; +- char line[1024]; +- int bus_num, addr, speed, class_id, product_id, vendor_id; +- int ret = 0; +- char port[MAX_PORTLEN]; +- char product_name[512]; +- struct dirent *de; +- +- dir = opendir("/sys/bus/usb/devices"); +- if (!dir) { +- perror("husb: opendir /sys/bus/usb/devices"); +- fprintf(stderr, "husb: please make sure sysfs is mounted at /sys\n"); +- goto the_end; +- } +- +- while ((de = readdir(dir))) { +- if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) { +- if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) { +- continue; +- } +- +- if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) { +- goto the_end; +- } +- if (sscanf(line, "%d", &addr) != 1) { +- goto the_end; +- } +- if (!usb_host_read_file(line, sizeof(line), "bDeviceClass", +- de->d_name)) { +- goto the_end; +- } +- if (sscanf(line, "%x", &class_id) != 1) { +- goto the_end; +- } +- +- if (!usb_host_read_file(line, sizeof(line), "idVendor", +- de->d_name)) { +- goto the_end; +- } +- if (sscanf(line, "%x", &vendor_id) != 1) { +- goto the_end; +- } +- if (!usb_host_read_file(line, sizeof(line), "idProduct", +- de->d_name)) { +- goto the_end; +- } +- if (sscanf(line, "%x", &product_id) != 1) { +- goto the_end; +- } +- if (!usb_host_read_file(line, sizeof(line), "product", +- de->d_name)) { +- *product_name = 0; +- } else { +- if (strlen(line) > 0) { +- line[strlen(line) - 1] = '\0'; +- } +- pstrcpy(product_name, sizeof(product_name), line); +- } +- +- if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) { +- goto the_end; +- } +- if (!strcmp(line, "5000\n")) { +- speed = USB_SPEED_SUPER; +- } else if (!strcmp(line, "480\n")) { +- speed = USB_SPEED_HIGH; +- } else if (!strcmp(line, "1.5\n")) { +- speed = USB_SPEED_LOW; +- } else { +- speed = USB_SPEED_FULL; +- } +- +- ret = func(opaque, bus_num, addr, port, class_id, vendor_id, +- product_id, product_name, speed); +- if (ret) { +- goto the_end; +- } +- } +- } +- the_end: +- if (dir) { +- closedir(dir); +- } +- return ret; +-} +- +-static QEMUTimer *usb_auto_timer; +-static VMChangeStateEntry *usb_vmstate; +- +-static int usb_host_auto_scan(void *opaque, int bus_num, +- int addr, const char *port, +- int class_id, int vendor_id, int product_id, +- const char *product_name, int speed) +-{ +- struct USBAutoFilter *f; +- struct USBHostDevice *s; +- +- /* Ignore hubs */ +- if (class_id == 9) +- return 0; +- +- QTAILQ_FOREACH(s, &hostdevs, next) { +- f = &s->match; +- +- if (f->bus_num > 0 && f->bus_num != bus_num) { +- continue; +- } +- if (f->addr > 0 && f->addr != addr) { +- continue; +- } +- if (f->port != NULL && strcmp(f->port, port) != 0) { +- continue; +- } +- +- if (f->vendor_id > 0 && f->vendor_id != vendor_id) { +- continue; +- } +- +- if (f->product_id > 0 && f->product_id != product_id) { +- continue; +- } +- /* We got a match */ +- s->seen++; +- if (s->errcount >= 3) { +- return 0; +- } +- +- /* Already attached ? */ +- if (s->fd != -1) { +- return 0; +- } +- DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr); +- +- if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) { +- s->errcount++; +- } +- break; +- } +- +- return 0; +-} +- +-static void usb_host_vm_state(void *unused, int running, RunState state) +-{ +- if (running) { +- usb_host_auto_check(unused); +- } +-} +- +-static void usb_host_auto_check(void *unused) +-{ +- struct USBHostDevice *s; +- int unconnected = 0; +- +- if (runstate_is_running()) { +- usb_host_scan(NULL, usb_host_auto_scan); +- +- QTAILQ_FOREACH(s, &hostdevs, next) { +- if (s->fd == -1) { +- unconnected++; +- } +- if (s->seen == 0) { +- s->errcount = 0; +- } +- s->seen = 0; +- } +- +- if (unconnected == 0) { +- /* nothing to watch */ +- if (usb_auto_timer) { +- qemu_del_timer(usb_auto_timer); +- trace_usb_host_auto_scan_disabled(); +- } +- return; +- } +- } +- +- if (!usb_vmstate) { +- usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL); +- } +- if (!usb_auto_timer) { +- usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL); +- if (!usb_auto_timer) { +- return; +- } +- trace_usb_host_auto_scan_enabled(); +- } +- qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000); +-} +- +-#ifndef CONFIG_USB_LIBUSB +- +-/**********************/ +-/* USB host device info */ +- +-struct usb_class_info { +- int class; +- const char *class_name; +-}; +- +-static const struct usb_class_info usb_class_info[] = { +- { USB_CLASS_AUDIO, "Audio"}, +- { USB_CLASS_COMM, "Communication"}, +- { USB_CLASS_HID, "HID"}, +- { USB_CLASS_HUB, "Hub" }, +- { USB_CLASS_PHYSICAL, "Physical" }, +- { USB_CLASS_PRINTER, "Printer" }, +- { USB_CLASS_MASS_STORAGE, "Storage" }, +- { USB_CLASS_CDC_DATA, "Data" }, +- { USB_CLASS_APP_SPEC, "Application Specific" }, +- { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, +- { USB_CLASS_STILL_IMAGE, "Still Image" }, +- { USB_CLASS_CSCID, "Smart Card" }, +- { USB_CLASS_CONTENT_SEC, "Content Security" }, +- { -1, NULL } +-}; +- +-static const char *usb_class_str(uint8_t class) +-{ +- const struct usb_class_info *p; +- for(p = usb_class_info; p->class != -1; p++) { +- if (p->class == class) { +- break; +- } +- } +- return p->class_name; +-} +- +-static void usb_info_device(Monitor *mon, int bus_num, +- int addr, const char *port, +- int class_id, int vendor_id, int product_id, +- const char *product_name, +- int speed) +-{ +- const char *class_str, *speed_str; +- +- switch(speed) { +- case USB_SPEED_LOW: +- speed_str = "1.5"; +- break; +- case USB_SPEED_FULL: +- speed_str = "12"; +- break; +- case USB_SPEED_HIGH: +- speed_str = "480"; +- break; +- case USB_SPEED_SUPER: +- speed_str = "5000"; +- break; +- default: +- speed_str = "?"; +- break; +- } +- +- monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n", +- bus_num, addr, port, speed_str); +- class_str = usb_class_str(class_id); +- if (class_str) { +- monitor_printf(mon, " %s:", class_str); +- } else { +- monitor_printf(mon, " Class %02x:", class_id); +- } +- monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id); +- if (product_name[0] != '\0') { +- monitor_printf(mon, ", %s", product_name); +- } +- monitor_printf(mon, "\n"); +-} +- +-static int usb_host_info_device(void *opaque, int bus_num, int addr, +- const char *path, int class_id, +- int vendor_id, int product_id, +- const char *product_name, +- int speed) +-{ +- Monitor *mon = opaque; +- +- usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id, +- product_name, speed); +- return 0; +-} +- +-static void dec2str(int val, char *str, size_t size) +-{ +- if (val == 0) { +- snprintf(str, size, "*"); +- } else { +- snprintf(str, size, "%d", val); +- } +-} +- +-static void hex2str(int val, char *str, size_t size) +-{ +- if (val == 0) { +- snprintf(str, size, "*"); +- } else { +- snprintf(str, size, "%04x", val); +- } +-} +- +-void usb_host_info(Monitor *mon, const QDict *qdict) +-{ +- struct USBAutoFilter *f; +- struct USBHostDevice *s; +- +- usb_host_scan(mon, usb_host_info_device); +- +- if (QTAILQ_EMPTY(&hostdevs)) { +- return; +- } +- +- monitor_printf(mon, " Auto filters:\n"); +- QTAILQ_FOREACH(s, &hostdevs, next) { +- char bus[10], addr[10], vid[10], pid[10]; +- f = &s->match; +- dec2str(f->bus_num, bus, sizeof(bus)); +- dec2str(f->addr, addr, sizeof(addr)); +- hex2str(f->vendor_id, vid, sizeof(vid)); +- hex2str(f->product_id, pid, sizeof(pid)); +- monitor_printf(mon, " Bus %s, Addr %s, Port %s, ID %s:%s\n", +- bus, addr, f->port ? f->port : "*", vid, pid); +- } +-} +- +-#endif +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-QEMU-AER-Qemu-changes-to-support-AER-for-VFIO-PCI-devices.patch b/SOURCES/kvm-vfio-QEMU-AER-Qemu-changes-to-support-AER-for-VFIO-PCI-devices.patch new file mode 100644 index 0000000..46033e2 --- /dev/null +++ b/SOURCES/kvm-vfio-QEMU-AER-Qemu-changes-to-support-AER-for-VFIO-PCI-devices.patch @@ -0,0 +1,226 @@ +From 742bae4cea60c8601bbb6e5ec643167d8ca664d7 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 6 Aug 2013 19:52:04 +0200 +Subject: vfio: QEMU-AER: Qemu changes to support AER for VFIO-PCI devices + +RH-Author: Nigel Croxon +Message-id: <1375818724-41239-3-git-send-email-ncroxon@redhat.com> +Patchwork-id: 53017 +O-Subject: [RHEL7.0 qemu-kvm PATCH v2 2/2] vfio: QEMU-AER: Qemu changes to support AER for VFIO-PCI devices +Bugzilla: 984604 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Alex Williamson +RH-Acked-by: Miroslav Rezanina + +From: Vijay Mohan Pandarathil + +Add support for error containment when a VFIO device assigned to a KVM +guest encounters an error. This is for PCIe devices/drivers that support AER +functionality. When the host OS is notified of an error in a device either +through the firmware first approach or through an interrupt handled by the AER +root port driver, the error handler registered by the vfio-pci driver gets +invoked. The qemu process is signaled through an eventfd registered per +VFIO device by the qemu process. In the eventfd handler, qemu decides on +what action to take. In this implementation, guest is brought down to +contain the error. + +The kernel patches for the above functionality has been already accepted. + +This is a refresh of the QEMU patch which was reviewed earlier. +http://marc.info/?l=linux-kernel&m=136281557608087&w=2 +This patch has the same contents and has been built after refreshing +to latest upstream and after the linux headers have been updated in qemu. + + - Create eventfd per vfio device assigned to a guest and register an + event handler + + - This fd is passed to the vfio_pci driver through the SET_IRQ ioctl + + - When the device encounters an error, the eventfd is signalled + and the qemu eventfd handler gets invoked. + + - In the handler decide what action to take. Current action taken + is to stop the guest. + +Signed-off-by: Vijay Mohan Pandarathil +Signed-off-by: Alex Williamson +(cherry picked from commit 7b4b0e9eda51902b53bc1a2318df53cdb8b72eed) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 693a9ff..f8fef8c 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -158,6 +158,7 @@ typedef struct VFIODevice { + PCIHostDeviceAddress host; + QLIST_ENTRY(VFIODevice) next; + struct VFIOGroup *group; ++ EventNotifier err_notifier; + uint32_t features; + #define VFIO_FEATURE_ENABLE_VGA_BIT 0 + #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) +@@ -165,6 +166,7 @@ typedef struct VFIODevice { + uint8_t pm_cap; + bool reset_works; + bool has_vga; ++ bool pci_aer; + } VFIODevice; + + typedef struct VFIOGroup { +@@ -2776,6 +2778,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) + { + struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) }; + struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; ++ struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) }; + int ret, i; + + ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name); +@@ -2919,6 +2922,19 @@ 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); ++ if (ret) { ++ /* This can fail for an old kernel or legacy PCI dev */ ++ DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure ret=%d\n", ret); ++ ret = 0; ++ } else if (irq_info.count == 1) { ++ vdev->pci_aer = true; ++ } else { ++ error_report("vfio: Warning: " ++ "Could not enable error recovery for the device\n"); ++ } + + error: + if (ret) { +@@ -2941,6 +2957,113 @@ static void vfio_put_device(VFIODevice *vdev) + } + } + ++static void vfio_err_notifier_handler(void *opaque) ++{ ++ VFIODevice *vdev = opaque; ++ ++ if (!event_notifier_test_and_clear(&vdev->err_notifier)) { ++ return; ++ } ++ ++ /* ++ * TBD. Retrieve the error details and decide what action ++ * needs to be taken. One of the actions could be to pass ++ * the error to the guest and have the guest driver recover ++ * from the error. This requires that PCIe capabilities be ++ * exposed to the guest. For now, we just terminate the ++ * guest to contain the error. ++ */ ++ ++ error_report("%s (%04x:%02x:%02x.%x)" ++ "Unrecoverable error detected...\n" ++ "Please collect any data possible and then kill the guest", ++ __func__, vdev->host.domain, vdev->host.bus, ++ vdev->host.slot, vdev->host.function); ++ ++ vm_stop(RUN_STATE_IO_ERROR); ++} ++ ++/* ++ * Registers error notifier for devices supporting error recovery. ++ * If we encounter a failure in this function, we report an error ++ * and continue after disabling error recovery support for the ++ * device. ++ */ ++static void vfio_register_err_notifier(VFIODevice *vdev) ++{ ++ int ret; ++ int argsz; ++ struct vfio_irq_set *irq_set; ++ int32_t *pfd; ++ ++ if (!vdev->pci_aer) { ++ return; ++ } ++ ++ if (event_notifier_init(&vdev->err_notifier, 0)) { ++ error_report("vfio: Warning: " ++ "Unable to init event notifier for error detection\n"); ++ vdev->pci_aer = false; ++ 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_ERR_IRQ_INDEX; ++ irq_set->start = 0; ++ irq_set->count = 1; ++ pfd = (int32_t *)&irq_set->data; ++ ++ *pfd = event_notifier_get_fd(&vdev->err_notifier); ++ qemu_set_fd_handler(*pfd, vfio_err_notifier_handler, NULL, vdev); ++ ++ ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); ++ if (ret) { ++ error_report("vfio: Failed to set up error notification\n"); ++ qemu_set_fd_handler(*pfd, NULL, NULL, vdev); ++ event_notifier_cleanup(&vdev->err_notifier); ++ vdev->pci_aer = false; ++ } ++ g_free(irq_set); ++} ++ ++static void vfio_unregister_err_notifier(VFIODevice *vdev) ++{ ++ int argsz; ++ struct vfio_irq_set *irq_set; ++ int32_t *pfd; ++ int ret; ++ ++ if (!vdev->pci_aer) { ++ 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_ERR_IRQ_INDEX; ++ irq_set->start = 0; ++ irq_set->count = 1; ++ pfd = (int32_t *)&irq_set->data; ++ *pfd = -1; ++ ++ ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); ++ if (ret) { ++ error_report("vfio: Failed to de-assign error fd: %d\n", ret); ++ } ++ g_free(irq_set); ++ qemu_set_fd_handler(event_notifier_get_fd(&vdev->err_notifier), ++ NULL, NULL, vdev); ++ event_notifier_cleanup(&vdev->err_notifier); ++} ++ + static int vfio_initfn(PCIDevice *pdev) + { + VFIODevice *pvdev, *vdev = DO_UPCAST(VFIODevice, pdev, pdev); +@@ -3073,6 +3196,7 @@ static int vfio_initfn(PCIDevice *pdev) + } + + add_boot_device_path(vdev->bootindex, &pdev->qdev, NULL); ++ vfio_register_err_notifier(vdev); + + return 0; + +@@ -3092,6 +3216,7 @@ static void vfio_exitfn(PCIDevice *pdev) + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); + VFIOGroup *group = vdev->group; + ++ vfio_unregister_err_notifier(vdev); + pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); + vfio_disable_interrupts(vdev); + if (vdev->intx.mmap_timer) { diff --git a/SOURCES/kvm-vfio-pci-Add-dummy-PCI-ROM-write-accessor.patch b/SOURCES/kvm-vfio-pci-Add-dummy-PCI-ROM-write-accessor.patch new file mode 100644 index 0000000..f5be0ab --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Add-dummy-PCI-ROM-write-accessor.patch @@ -0,0 +1,53 @@ +From 0d04efadb8289105d4ab7632c8b6d70b860a22c6 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:37:46 +0100 +Subject: [PATCH 16/25] vfio-pci: Add dummy PCI ROM write accessor + +RH-Author: Alex Williamson +Message-id: <20131105153746.16057.36730.stgit@bling.home> +Patchwork-id: 55425 +O-Subject: [RHEL7 qemu-kvm PATCH 4/5] vfio-pci: Add dummy PCI ROM write accessor +Bugzilla: 1026550 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1026550 +Upstream commit: 64fa25a0efcadda6e8197e8ea578f6117d01bb4b + +Just to be sure we don't jump off any NULL pointer cliffs. + +Signed-off-by: Alex Williamson +Reported-by: Paolo Bonzini +--- + hw/misc/vfio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 6 ++++++ + 1 files changed, 6 insertions(+), 0 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index e336021..d327b40 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -1127,8 +1127,14 @@ static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size) + return val; + } + ++static void vfio_rom_write(void *opaque, hwaddr addr, ++ uint64_t data, unsigned size) ++{ ++} ++ + static const MemoryRegionOps vfio_rom_ops = { + .read = vfio_rom_read, ++ .write = vfio_rom_write, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Add-support-for-MSI-affinity.patch b/SOURCES/kvm-vfio-pci-Add-support-for-MSI-affinity.patch new file mode 100644 index 0000000..1894127 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Add-support-for-MSI-affinity.patch @@ -0,0 +1,134 @@ +From 6f572c45ff2c2376a16cd15882067d7fdcd74a83 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:30:40 +0100 +Subject: [PATCH 12/25] vfio-pci: Add support for MSI affinity +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Alex Williamson +Message-id: <20131105153040.15749.78283.stgit@bling.home> +Patchwork-id: 55413 +O-Subject: [RHEL7 qemu-kvm PATCH v2 2/2] vfio-pci: Add support for MSI affinity +Bugzilla: 1025477 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Jeffrey Cody + +Bugzilla: 1025477 +Upstream commit: c7679d450ee021eb0826be65e4e018884443643a + +When MSI is accelerated through KVM the vectors are only programmed +when the guest first enables MSI support.  Subsequent writes to the +vector address or data fields are ignored.  Unfortunately that means +we're ignore updates done to adjust SMP affinity of the vectors. +MSI SMP affinity already works in non-KVM mode because the address +and data fields are read from their backing store on each interrupt. + +This patch stores the MSIMessage programmed into KVM so that we can +determine when changes are made and update the routes. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 47 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 47 ++++++++++++++++++++++++++++++++++++++++------- + 1 files changed, 40 insertions(+), 7 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index a072fd9..286dad1 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -119,6 +119,7 @@ typedef struct VFIOINTx { + typedef struct VFIOMSIVector { + EventNotifier interrupt; /* eventfd triggered on interrupt */ + struct VFIODevice *vdev; /* back pointer to device */ ++ MSIMessage msg; /* cache the MSI message so we know when it changes */ + int virq; /* KVM irqchip route for QEMU bypass */ + bool use; + } VFIOMSIVector; +@@ -795,7 +796,6 @@ retry: + vdev->msi_vectors = g_malloc0(vdev->nr_vectors * sizeof(VFIOMSIVector)); + + for (i = 0; i < vdev->nr_vectors; i++) { +- MSIMessage msg; + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + + vector->vdev = vdev; +@@ -805,13 +805,13 @@ retry: + error_report("vfio: Error: event_notifier_init failed"); + } + +- msg = msi_get_message(&vdev->pdev, i); ++ vector->msg = msi_get_message(&vdev->pdev, i); + + /* + * Attempt to enable route through KVM irqchip, + * default to userspace handling if unavailable. + */ +- vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg); ++ vector->virq = kvm_irqchip_add_msi_route(kvm_state, vector->msg); + if (vector->virq < 0 || + kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, + vector->virq) < 0) { +@@ -917,6 +917,33 @@ static void vfio_disable_msi(VFIODevice *vdev) + vdev->host.bus, vdev->host.slot, vdev->host.function); + } + ++static void vfio_update_msi(VFIODevice *vdev) ++{ ++ int i; ++ ++ for (i = 0; i < vdev->nr_vectors; i++) { ++ VFIOMSIVector *vector = &vdev->msi_vectors[i]; ++ MSIMessage msg; ++ ++ if (!vector->use || vector->virq < 0) { ++ continue; ++ } ++ ++ msg = msi_get_message(&vdev->pdev, i); ++ ++ if (msg.address != vector->msg.address || ++ msg.data != vector->msg.data) { ++ ++ DPRINTF("%s(%04x:%02x:%02x.%x) MSI vector %d changed\n", ++ __func__, vdev->host.domain, vdev->host.bus, ++ vdev->host.slot, vdev->host.function, i); ++ ++ kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg); ++ vector->msg = msg; ++ } ++ } ++} ++ + /* + * IO Port/MMIO - Beware of the endians, VFIO is always little endian + */ +@@ -1834,10 +1861,16 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, + + is_enabled = msi_enabled(pdev); + +- if (!was_enabled && is_enabled) { +- vfio_enable_msi(vdev); +- } else if (was_enabled && !is_enabled) { +- vfio_disable_msi(vdev); ++ if (!was_enabled) { ++ if (is_enabled) { ++ vfio_enable_msi(vdev); ++ } ++ } else { ++ if (!is_enabled) { ++ vfio_disable_msi(vdev); ++ } else { ++ vfio_update_msi(vdev); ++ } + } + } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX && + ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) { +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Cleanup-error_reports.patch b/SOURCES/kvm-vfio-pci-Cleanup-error_reports.patch new file mode 100644 index 0000000..e2e5beb --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Cleanup-error_reports.patch @@ -0,0 +1,100 @@ +From 2f16dbb9130d90415c9db17ac8d28a196515b109 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:37:40 +0100 +Subject: [PATCH 15/25] vfio-pci: Cleanup error_reports + +RH-Author: Alex Williamson +Message-id: <20131105153740.16057.95138.stgit@bling.home> +Patchwork-id: 55424 +O-Subject: [RHEL7 qemu-kvm PATCH 3/5] vfio-pci: Cleanup error_reports +Bugzilla: 1026550 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1026550 +Upstream commit: 8fbf47c3a8a7f37a11268a07290d20a325ba4cb6 + +Remove carriage returns and tweak formatting for error_reports. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 24 ++++++++++++------------ + 1 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 8d84891..e336021 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -3050,13 +3050,15 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); + if (ret) { + /* This can fail for an old kernel or legacy PCI dev */ +- DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure ret=%d\n", ret); ++ DPRINTF("VFIO_DEVICE_GET_IRQ_INFO failure: %m\n"); + ret = 0; + } else if (irq_info.count == 1) { + vdev->pci_aer = true; + } else { +- error_report("vfio: Warning: " +- "Could not enable error recovery for the device\n"); ++ error_report("vfio: %04x:%02x:%02x.%x " ++ "Could not enable error recovery for the device", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); + } + + error: +@@ -3097,11 +3099,10 @@ static void vfio_err_notifier_handler(void *opaque) + * guest to contain the error. + */ + +- error_report("%s (%04x:%02x:%02x.%x)" +- "Unrecoverable error detected...\n" +- "Please collect any data possible and then kill the guest", +- __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function); ++ error_report("%s(%04x:%02x:%02x.%x) Unrecoverable error detected. " ++ "Please collect any data possible and then kill the guest", ++ __func__, vdev->host.domain, vdev->host.bus, ++ vdev->host.slot, vdev->host.function); + + vm_stop(RUN_STATE_IO_ERROR); + } +@@ -3124,8 +3125,7 @@ static void vfio_register_err_notifier(VFIODevice *vdev) + } + + if (event_notifier_init(&vdev->err_notifier, 0)) { +- error_report("vfio: Warning: " +- "Unable to init event notifier for error detection\n"); ++ error_report("vfio: Unable to init event notifier for error detection"); + vdev->pci_aer = false; + return; + } +@@ -3146,7 +3146,7 @@ static void vfio_register_err_notifier(VFIODevice *vdev) + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { +- error_report("vfio: Failed to set up error notification\n"); ++ error_report("vfio: Failed to set up error notification"); + qemu_set_fd_handler(*pfd, NULL, NULL, vdev); + event_notifier_cleanup(&vdev->err_notifier); + vdev->pci_aer = false; +@@ -3179,7 +3179,7 @@ static void vfio_unregister_err_notifier(VFIODevice *vdev) + + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set); + if (ret) { +- error_report("vfio: Failed to de-assign error fd: %d\n", ret); ++ error_report("vfio: Failed to de-assign error fd: %m"); + } + g_free(irq_set); + qemu_set_fd_handler(event_notifier_get_fd(&vdev->err_notifier), +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Fix-endian-issues-in-vfio_pci_size_rom.patch b/SOURCES/kvm-vfio-pci-Fix-endian-issues-in-vfio_pci_size_rom.patch new file mode 100644 index 0000000..b07fe46 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Fix-endian-issues-in-vfio_pci_size_rom.patch @@ -0,0 +1,57 @@ +From 4bb91ae660a2b4aa64c12b9f92227881edf13609 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:37:52 +0100 +Subject: [PATCH 17/25] vfio-pci: Fix endian issues in vfio_pci_size_rom() + +RH-Author: Alex Williamson +Message-id: <20131105153752.16057.43832.stgit@bling.home> +Patchwork-id: 55426 +O-Subject: [RHEL7 qemu-kvm PATCH 5/5] vfio-pci: Fix endian issues in vfio_pci_size_rom() +Bugzilla: 1026550 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1026550 +Upstream commit: b1c50c5f248805be747e96e89efbe784ee99f764 + +VFIO is always little endian so do byte swapping of our mask on the +way in and byte swapping of the size on the way out. + +Signed-off-by: Alex Williamson +Reported-by: Alexey Kardashevskiy +--- + hw/misc/vfio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index d327b40..6178221 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -1140,7 +1140,7 @@ static const MemoryRegionOps vfio_rom_ops = { + + static void vfio_pci_size_rom(VFIODevice *vdev) + { +- uint32_t orig, size = (uint32_t)PCI_ROM_ADDRESS_MASK; ++ uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK); + off_t offset = vdev->config_offset + PCI_ROM_ADDRESS; + char name[32]; + +@@ -1162,7 +1162,7 @@ static void vfio_pci_size_rom(VFIODevice *vdev) + return; + } + +- size = ~(size & PCI_ROM_ADDRESS_MASK) + 1; ++ size = ~(le32_to_cpu(size) & PCI_ROM_ADDRESS_MASK) + 1; + + if (!size) { + return; +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Implement-PCI-hot-reset.patch b/SOURCES/kvm-vfio-pci-Implement-PCI-hot-reset.patch new file mode 100644 index 0000000..9cdf5ee --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Implement-PCI-hot-reset.patch @@ -0,0 +1,444 @@ +From 8ea5e0ba0b1ba054d71bb10f8c45c167dd3d7792 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 17:31:11 +0100 +Subject: [PATCH 19/25] vfio-pci: Implement PCI hot reset + +RH-Author: Alex Williamson +Message-id: <20131105173110.19372.22420.stgit@bling.home> +Patchwork-id: 55440 +O-Subject: [RHEL7 qemu-kvm PATCH 2/2] vfio-pci: Implement PCI hot reset +Bugzilla: 1025472 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1025472 +Upstream commit: f16f39c3fc973c5d7cbc2224eefb4ef5eb1e64ff + +Now that VFIO has a PCI hot reset interface, take advantage of it. +There are two modes that we need to consider. The first is when only +one device within the set of devices affected is actually assigned to +the guest. In this case the other devices are are just held by VFIO +for isolation and we can pretend they're not there, doing an entire +bus reset whenever the device reset callback is triggered. Supporting +this case separately allows us to do the best reset we can do of the +device even if the device is hotplugged. + +The second mode is when multiple affected devices are all exposed to +the guest. In this case we can only do a hot reset when the entire +system is being reset. However, this also allows us to track which +individual devices are affected by a reset and only do them once. + +We split our reset function into pre- and post-reset helper functions +prioritize the types of device resets available to us, and create +separate _one vs _multi reset interfaces to handle the distinct cases +above. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 300 insertions(+), 38 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 338 +++++++++++++++++++++++++++++++++++++++++++++++++------- + 1 files changed, 300 insertions(+), 38 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 6178221..331ae5f 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -188,6 +188,7 @@ typedef struct VFIODevice { + bool pci_aer; + bool has_flr; + bool has_pm_reset; ++ bool needs_reset; + } VFIODevice; + + typedef struct VFIOGroup { +@@ -2759,6 +2760,279 @@ static int vfio_add_capabilities(VFIODevice *vdev) + return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]); + } + ++static void vfio_pci_pre_reset(VFIODevice *vdev) ++{ ++ PCIDevice *pdev = &vdev->pdev; ++ uint16_t cmd; ++ ++ vfio_disable_interrupts(vdev); ++ ++ /* Make sure the device is in D0 */ ++ if (vdev->pm_cap) { ++ uint16_t pmcsr; ++ uint8_t state; ++ ++ pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2); ++ state = pmcsr & PCI_PM_CTRL_STATE_MASK; ++ if (state) { ++ pmcsr &= ~PCI_PM_CTRL_STATE_MASK; ++ vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2); ++ /* vfio handles the necessary delay here */ ++ pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2); ++ state = pmcsr & PCI_PM_CTRL_STATE_MASK; ++ if (state) { ++ error_report("vfio: Unable to power on device, stuck in D%d\n", ++ state); ++ } ++ } ++ } ++ ++ /* ++ * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master. ++ * Also put INTx Disable in known state. ++ */ ++ cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2); ++ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | ++ PCI_COMMAND_INTX_DISABLE); ++ vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2); ++} ++ ++static void vfio_pci_post_reset(VFIODevice *vdev) ++{ ++ vfio_enable_intx(vdev); ++} ++ ++static bool vfio_pci_host_match(PCIHostDeviceAddress *host1, ++ PCIHostDeviceAddress *host2) ++{ ++ return (host1->domain == host2->domain && host1->bus == host2->bus && ++ host1->slot == host2->slot && host1->function == host2->function); ++} ++ ++static int vfio_pci_hot_reset(VFIODevice *vdev, bool single) ++{ ++ VFIOGroup *group; ++ struct vfio_pci_hot_reset_info *info; ++ struct vfio_pci_dependent_device *devices; ++ struct vfio_pci_hot_reset *reset; ++ int32_t *fds; ++ int ret, i, count; ++ bool multi = false; ++ ++ DPRINTF("%s(%04x:%02x:%02x.%x) %s\n", __func__, vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function, ++ single ? "one" : "multi"); ++ ++ vfio_pci_pre_reset(vdev); ++ vdev->needs_reset = false; ++ ++ info = g_malloc0(sizeof(*info)); ++ info->argsz = sizeof(*info); ++ ++ ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info); ++ if (ret && errno != ENOSPC) { ++ ret = -errno; ++ if (!vdev->has_pm_reset) { ++ error_report("vfio: Cannot reset device %04x:%02x:%02x.%x, " ++ "no available reset mechanism.", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function); ++ } ++ goto out_single; ++ } ++ ++ count = info->count; ++ info = g_realloc(info, sizeof(*info) + (count * sizeof(*devices))); ++ info->argsz = sizeof(*info) + (count * sizeof(*devices)); ++ devices = &info->devices[0]; ++ ++ ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info); ++ if (ret) { ++ ret = -errno; ++ error_report("vfio: hot reset info failed: %m"); ++ goto out_single; ++ } ++ ++ DPRINTF("%04x:%02x:%02x.%x: hot reset dependent devices:\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ ++ /* Verify that we have all the groups required */ ++ for (i = 0; i < info->count; i++) { ++ PCIHostDeviceAddress host; ++ VFIODevice *tmp; ++ ++ host.domain = devices[i].segment; ++ host.bus = devices[i].bus; ++ host.slot = PCI_SLOT(devices[i].devfn); ++ host.function = PCI_FUNC(devices[i].devfn); ++ ++ DPRINTF("\t%04x:%02x:%02x.%x group %d\n", host.domain, ++ host.bus, host.slot, host.function, devices[i].group_id); ++ ++ if (vfio_pci_host_match(&host, &vdev->host)) { ++ continue; ++ } ++ ++ QLIST_FOREACH(group, &group_list, next) { ++ if (group->groupid == devices[i].group_id) { ++ break; ++ } ++ } ++ ++ if (!group) { ++ if (!vdev->has_pm_reset) { ++ error_report("vfio: Cannot reset device %04x:%02x:%02x.%x, " ++ "depends on group %d which is not owned.", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function, devices[i].group_id); ++ } ++ ret = -EPERM; ++ goto out; ++ } ++ ++ /* Prep dependent devices for reset and clear our marker. */ ++ QLIST_FOREACH(tmp, &group->device_list, next) { ++ if (vfio_pci_host_match(&host, &tmp->host)) { ++ if (single) { ++ DPRINTF("vfio: found another in-use device " ++ "%04x:%02x:%02x.%x\n", host.domain, host.bus, ++ host.slot, host.function); ++ ret = -EINVAL; ++ goto out_single; ++ } ++ vfio_pci_pre_reset(tmp); ++ tmp->needs_reset = false; ++ multi = true; ++ break; ++ } ++ } ++ } ++ ++ if (!single && !multi) { ++ DPRINTF("vfio: No other in-use devices for multi hot reset\n"); ++ ret = -EINVAL; ++ goto out_single; ++ } ++ ++ /* Determine how many group fds need to be passed */ ++ count = 0; ++ QLIST_FOREACH(group, &group_list, next) { ++ for (i = 0; i < info->count; i++) { ++ if (group->groupid == devices[i].group_id) { ++ count++; ++ break; ++ } ++ } ++ } ++ ++ reset = g_malloc0(sizeof(*reset) + (count * sizeof(*fds))); ++ reset->argsz = sizeof(*reset) + (count * sizeof(*fds)); ++ fds = &reset->group_fds[0]; ++ ++ /* Fill in group fds */ ++ QLIST_FOREACH(group, &group_list, next) { ++ for (i = 0; i < info->count; i++) { ++ if (group->groupid == devices[i].group_id) { ++ fds[reset->count++] = group->fd; ++ break; ++ } ++ } ++ } ++ ++ /* Bus reset! */ ++ ret = ioctl(vdev->fd, VFIO_DEVICE_PCI_HOT_RESET, reset); ++ g_free(reset); ++ ++ DPRINTF("%04x:%02x:%02x.%x hot reset: %s\n", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function, ++ ret ? "%m" : "Success"); ++ ++out: ++ /* Re-enable INTx on affected devices */ ++ for (i = 0; i < info->count; i++) { ++ PCIHostDeviceAddress host; ++ VFIODevice *tmp; ++ ++ host.domain = devices[i].segment; ++ host.bus = devices[i].bus; ++ host.slot = PCI_SLOT(devices[i].devfn); ++ host.function = PCI_FUNC(devices[i].devfn); ++ ++ if (vfio_pci_host_match(&host, &vdev->host)) { ++ continue; ++ } ++ ++ QLIST_FOREACH(group, &group_list, next) { ++ if (group->groupid == devices[i].group_id) { ++ break; ++ } ++ } ++ ++ if (!group) { ++ break; ++ } ++ ++ QLIST_FOREACH(tmp, &group->device_list, next) { ++ if (vfio_pci_host_match(&host, &tmp->host)) { ++ vfio_pci_post_reset(tmp); ++ break; ++ } ++ } ++ } ++out_single: ++ vfio_pci_post_reset(vdev); ++ g_free(info); ++ ++ return ret; ++} ++ ++/* ++ * We want to differentiate hot reset of mulitple in-use devices vs hot reset ++ * of a single in-use device. VFIO_DEVICE_RESET will already handle the case ++ * of doing hot resets when there is only a single device per bus. The in-use ++ * here refers to how many VFIODevices are affected. A hot reset that affects ++ * multiple devices, but only a single in-use device, means that we can call ++ * it from our bus ->reset() callback since the extent is effectively a single ++ * device. This allows us to make use of it in the hotplug path. When there ++ * are multiple in-use devices, we can only trigger the hot reset during a ++ * system reset and thus from our reset handler. We separate _one vs _multi ++ * here so that we don't overlap and do a double reset on the system reset ++ * path where both our reset handler and ->reset() callback are used. Calling ++ * _one() will only do a hot reset for the one in-use devices case, calling ++ * _multi() will do nothing if a _one() would have been sufficient. ++ */ ++static int vfio_pci_hot_reset_one(VFIODevice *vdev) ++{ ++ return vfio_pci_hot_reset(vdev, true); ++} ++ ++static int vfio_pci_hot_reset_multi(VFIODevice *vdev) ++{ ++ return vfio_pci_hot_reset(vdev, false); ++} ++ ++static void vfio_pci_reset_handler(void *opaque) ++{ ++ VFIOGroup *group; ++ VFIODevice *vdev; ++ ++ QLIST_FOREACH(group, &group_list, next) { ++ QLIST_FOREACH(vdev, &group->device_list, next) { ++ if (!vdev->reset_works || (!vdev->has_flr && vdev->has_pm_reset)) { ++ vdev->needs_reset = true; ++ } ++ } ++ } ++ ++ QLIST_FOREACH(group, &group_list, next) { ++ QLIST_FOREACH(vdev, &group->device_list, next) { ++ if (vdev->needs_reset) { ++ vfio_pci_hot_reset_multi(vdev); ++ } ++ } ++ } ++} ++ + static int vfio_connect_container(VFIOGroup *group) + { + VFIOContainer *container; +@@ -2901,6 +3175,10 @@ static VFIOGroup *vfio_get_group(int groupid) + return NULL; + } + ++ if (QLIST_EMPTY(&group_list)) { ++ qemu_register_reset(vfio_pci_reset_handler, NULL); ++ } ++ + QLIST_INSERT_HEAD(&group_list, group, next); + + return group; +@@ -2917,6 +3195,10 @@ static void vfio_put_group(VFIOGroup *group) + DPRINTF("vfio_put_group: close group->fd\n"); + close(group->fd); + g_free(group); ++ ++ if (QLIST_EMPTY(&group_list)) { ++ qemu_unregister_reset(vfio_pci_reset_handler, NULL); ++ } + } + + static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) +@@ -2955,9 +3237,6 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) + } + + vdev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET); +- if (!vdev->reset_works) { +- error_report("Warning, device %s does not support reset", name); +- } + + if (dev_info.num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) { + error_report("vfio: unexpected number of io regions %u", +@@ -3363,51 +3642,34 @@ static void vfio_pci_reset(DeviceState *dev) + { + PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev); + VFIODevice *vdev = DO_UPCAST(VFIODevice, pdev, pdev); +- uint16_t cmd; + + DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, + vdev->host.bus, vdev->host.slot, vdev->host.function); + +- vfio_disable_interrupts(vdev); +- +- /* Make sure the device is in D0 */ +- if (vdev->pm_cap) { +- uint16_t pmcsr; +- uint8_t state; ++ vfio_pci_pre_reset(vdev); + +- pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2); +- state = pmcsr & PCI_PM_CTRL_STATE_MASK; +- if (state) { +- pmcsr &= ~PCI_PM_CTRL_STATE_MASK; +- vfio_pci_write_config(pdev, vdev->pm_cap + PCI_PM_CTRL, pmcsr, 2); +- /* vfio handles the necessary delay here */ +- pmcsr = vfio_pci_read_config(pdev, vdev->pm_cap + PCI_PM_CTRL, 2); +- state = pmcsr & PCI_PM_CTRL_STATE_MASK; +- if (state) { +- error_report("vfio: Unable to power on device, stuck in D%d\n", +- state); +- } +- } ++ if (vdev->reset_works && (vdev->has_flr || !vdev->has_pm_reset) && ++ !ioctl(vdev->fd, VFIO_DEVICE_RESET)) { ++ DPRINTF("%04x:%02x:%02x.%x FLR/VFIO_DEVICE_RESET\n", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function); ++ goto post_reset; + } + +- /* +- * Stop any ongoing DMA by disconecting I/O, MMIO, and bus master. +- * Also put INTx Disable in known state. +- */ +- cmd = vfio_pci_read_config(pdev, PCI_COMMAND, 2); +- cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | +- PCI_COMMAND_INTX_DISABLE); +- vfio_pci_write_config(pdev, PCI_COMMAND, cmd, 2); ++ /* See if we can do our own bus reset */ ++ if (!vfio_pci_hot_reset_one(vdev)) { ++ goto post_reset; ++ } + +- if (vdev->reset_works) { +- if (ioctl(vdev->fd, VFIO_DEVICE_RESET)) { +- error_report("vfio: Error unable to reset physical device " +- "(%04x:%02x:%02x.%x): %m", vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function); +- } ++ /* If nothing else works and the device supports PM reset, use it */ ++ if (vdev->reset_works && vdev->has_pm_reset && ++ !ioctl(vdev->fd, VFIO_DEVICE_RESET)) { ++ DPRINTF("%04x:%02x:%02x.%x PCI PM Reset\n", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function); ++ goto post_reset; + } + +- vfio_enable_intx(vdev); ++post_reset: ++ vfio_pci_post_reset(vdev); + } + + static Property vfio_pci_dev_properties[] = { +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Lazy-PCI-option-ROM-loading.patch b/SOURCES/kvm-vfio-pci-Lazy-PCI-option-ROM-loading.patch new file mode 100644 index 0000000..5cac9b3 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Lazy-PCI-option-ROM-loading.patch @@ -0,0 +1,282 @@ +From f3b05560b20866cadb604f0a5a6f4a7698d2e07b Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:37:35 +0100 +Subject: [PATCH 14/25] vfio-pci: Lazy PCI option ROM loading + +RH-Author: Alex Williamson +Message-id: <20131105153734.16057.77668.stgit@bling.home> +Patchwork-id: 55423 +O-Subject: [RHEL7 qemu-kvm PATCH 2/5] vfio-pci: Lazy PCI option ROM loading +Bugzilla: 1026550 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1026550 +Upstream commit: 6f864e6ec8812d5a5525a7861ca599c6bcabdebe + +During vfio-pci initfn, the device is not always in a state where the +option ROM can be read. In the case of graphics cards, there's often +no per function reset, which means we have host driver state affecting +whether the option ROM is usable. Ideally we want to move reading the +option ROM past any co-assigned device resets to the point where the +guest first tries to read the ROM itself. + +To accomplish this, we switch the memory region for the option rom to +an I/O region rather than a memory mapped region. This has the side +benefit that we don't waste KVM memory slots for a BAR where we don't +care about performance. This also allows us to delay loading the ROM +from the device until the first read by the guest. We then use the +PCI config space size of the ROM BAR when setting up the BAR through +QEMU PCI. + +Another benefit of this approach is that previously when a user set +the ROM to a file using the romfile= option, we still probed VFIO for +the parameters of the ROM, which can result in dmesg errors about an +invalid ROM. We now only probe VFIO to get the ROM contents if the +guest actually tries to read the ROM. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 184 +++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 122 insertions(+), 62 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 184 +++++++++++++++++++++++++++++++++++++------------------- + 1 files changed, 122 insertions(+), 62 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 8e69182..8d84891 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -166,6 +166,7 @@ typedef struct VFIODevice { + off_t config_offset; /* Offset of config space region within device fd */ + unsigned int rom_size; + off_t rom_offset; /* Offset of ROM region within device fd */ ++ void *rom; + int msi_cap_size; + VFIOMSIVector *msi_vectors; + VFIOMSIXInfo *msix; +@@ -1058,6 +1059,125 @@ static const MemoryRegionOps vfio_bar_ops = { + .endianness = DEVICE_LITTLE_ENDIAN, + }; + ++static void vfio_pci_load_rom(VFIODevice *vdev) ++{ ++ struct vfio_region_info reg_info = { ++ .argsz = sizeof(reg_info), ++ .index = VFIO_PCI_ROM_REGION_INDEX ++ }; ++ uint64_t size; ++ off_t off = 0; ++ size_t bytes; ++ ++ if (ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { ++ error_report("vfio: Error getting ROM info: %m"); ++ return; ++ } ++ ++ DPRINTF("Device %04x:%02x:%02x.%x ROM:\n", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function); ++ DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n", ++ (unsigned long)reg_info.size, (unsigned long)reg_info.offset, ++ (unsigned long)reg_info.flags); ++ ++ vdev->rom_size = size = reg_info.size; ++ vdev->rom_offset = reg_info.offset; ++ ++ if (!vdev->rom_size) { ++ return; ++ } ++ ++ vdev->rom = g_malloc(size); ++ memset(vdev->rom, 0xff, size); ++ ++ while (size) { ++ bytes = pread(vdev->fd, vdev->rom + off, size, vdev->rom_offset + off); ++ if (bytes == 0) { ++ break; ++ } else if (bytes > 0) { ++ off += bytes; ++ size -= bytes; ++ } else { ++ if (errno == EINTR || errno == EAGAIN) { ++ continue; ++ } ++ error_report("vfio: Error reading device ROM: %m"); ++ break; ++ } ++ } ++} ++ ++static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ VFIODevice *vdev = opaque; ++ uint64_t val = ((uint64_t)1 << (size * 8)) - 1; ++ ++ /* Load the ROM lazily when the guest tries to read it */ ++ if (unlikely(!vdev->rom)) { ++ vfio_pci_load_rom(vdev); ++ } ++ ++ memcpy(&val, vdev->rom + addr, ++ (addr < vdev->rom_size) ? MIN(size, vdev->rom_size - addr) : 0); ++ ++ DPRINTF("%s(%04x:%02x:%02x.%x, 0x%"HWADDR_PRIx", 0x%x) = 0x%"PRIx64"\n", ++ __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function, addr, size, val); ++ ++ return val; ++} ++ ++static const MemoryRegionOps vfio_rom_ops = { ++ .read = vfio_rom_read, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void vfio_pci_size_rom(VFIODevice *vdev) ++{ ++ uint32_t orig, size = (uint32_t)PCI_ROM_ADDRESS_MASK; ++ off_t offset = vdev->config_offset + PCI_ROM_ADDRESS; ++ char name[32]; ++ ++ if (vdev->pdev.romfile || !vdev->pdev.rom_bar) { ++ return; ++ } ++ ++ /* ++ * Use the same size ROM BAR as the physical device. The contents ++ * will get filled in later when the guest tries to read it. ++ */ ++ if (pread(vdev->fd, &orig, 4, offset) != 4 || ++ pwrite(vdev->fd, &size, 4, offset) != 4 || ++ pread(vdev->fd, &size, 4, offset) != 4 || ++ pwrite(vdev->fd, &orig, 4, offset) != 4) { ++ error_report("%s(%04x:%02x:%02x.%x) failed: %m", ++ __func__, vdev->host.domain, vdev->host.bus, ++ vdev->host.slot, vdev->host.function); ++ return; ++ } ++ ++ size = ~(size & PCI_ROM_ADDRESS_MASK) + 1; ++ ++ if (!size) { ++ return; ++ } ++ ++ DPRINTF("%04x:%02x:%02x.%x ROM size 0x%x\n", vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function, size); ++ ++ snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ ++ memory_region_init_io(&vdev->pdev.rom, ++ &vfio_rom_ops, vdev, name, size); ++ ++ pci_register_bar(&vdev->pdev, PCI_ROM_SLOT, ++ PCI_BASE_ADDRESS_SPACE_MEMORY, &vdev->pdev.rom); ++ ++ vdev->pdev.has_rom = true; ++} ++ + static void vfio_vga_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) + { +@@ -2633,51 +2753,6 @@ static int vfio_add_capabilities(VFIODevice *vdev) + return vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]); + } + +-static int vfio_load_rom(VFIODevice *vdev) +-{ +- uint64_t size = vdev->rom_size; +- char name[32]; +- off_t off = 0, voff = vdev->rom_offset; +- ssize_t bytes; +- void *ptr; +- +- /* If loading ROM from file, pci handles it */ +- if (vdev->pdev.romfile || !vdev->pdev.rom_bar || !size) { +- return 0; +- } +- +- DPRINTF("%s(%04x:%02x:%02x.%x)\n", __func__, vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function); +- +- snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom", +- vdev->host.domain, vdev->host.bus, vdev->host.slot, +- vdev->host.function); +- memory_region_init_ram(&vdev->pdev.rom, name, size); +- ptr = memory_region_get_ram_ptr(&vdev->pdev.rom); +- memset(ptr, 0xff, size); +- +- while (size) { +- bytes = pread(vdev->fd, ptr + off, size, voff + off); +- if (bytes == 0) { +- break; /* expect that we could get back less than the ROM BAR */ +- } else if (bytes > 0) { +- off += bytes; +- size -= bytes; +- } else { +- if (errno == EINTR || errno == EAGAIN) { +- continue; +- } +- error_report("vfio: Error reading device ROM: %m"); +- memory_region_destroy(&vdev->pdev.rom); +- return -errno; +- } +- } +- +- pci_register_bar(&vdev->pdev, PCI_ROM_SLOT, 0, &vdev->pdev.rom); +- vdev->pdev.has_rom = true; +- return 0; +-} +- + static int vfio_connect_container(VFIOGroup *group) + { + VFIOContainer *container; +@@ -2911,22 +2986,6 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) + QLIST_INIT(&vdev->bars[i].quirks); + } + +- reg_info.index = VFIO_PCI_ROM_REGION_INDEX; +- +- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); +- if (ret) { +- error_report("vfio: Error getting ROM info: %m"); +- goto error; +- } +- +- DPRINTF("Device %s ROM:\n", name); +- DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n", +- (unsigned long)reg_info.size, (unsigned long)reg_info.offset, +- (unsigned long)reg_info.flags); +- +- vdev->rom_size = reg_info.size; +- vdev->rom_offset = reg_info.offset; +- + reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX; + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); +@@ -3224,7 +3283,7 @@ static int vfio_initfn(PCIDevice *pdev) + memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24); + memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4); + +- vfio_load_rom(vdev); ++ vfio_pci_size_rom(vdev); + + ret = vfio_early_setup_msix(vdev); + if (ret) { +@@ -3289,6 +3348,7 @@ static void vfio_exitfn(PCIDevice *pdev) + vfio_teardown_msi(vdev); + vfio_unmap_bars(vdev); + g_free(vdev->emulated_config_bits); ++ g_free(vdev->rom); + vfio_put_device(vdev); + vfio_put_group(group); + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Make-use-of-new-KVM-VFIO-device.patch b/SOURCES/kvm-vfio-pci-Make-use-of-new-KVM-VFIO-device.patch new file mode 100644 index 0000000..e041cb0 --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Make-use-of-new-KVM-VFIO-device.patch @@ -0,0 +1,131 @@ +From 3f6f409e0c66e7f67d8830ffce9576ca306853ff Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 17:51:11 +0100 +Subject: [PATCH 21/25] vfio-pci: Make use of new KVM-VFIO device + +RH-Author: Alex Williamson +Message-id: <20131105175111.19705.95280.stgit@bling.home> +Patchwork-id: 55443 +O-Subject: [RHEL7 qemu-kvm PATCH 2/2] vfio-pci: Make use of new KVM-VFIO device +Bugzilla: 1025474 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1025474 +Upstream: Posted - http://lists.nongnu.org/archive/html/qemu-devel/2013-11/msg00091.html + +Add and remove groups from the KVM virtual VFIO device as we make +use of them. This allows KVM to optimize for performance and +correctness based on properties of the group. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 65 insertions(+), 0 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 331ae5f..b7f213b 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -208,6 +208,15 @@ static QLIST_HEAD(, VFIOContainer) + static QLIST_HEAD(, VFIOGroup) + group_list = QLIST_HEAD_INITIALIZER(group_list); + ++/* ++ * We have a single VFIO pseudo device per KVM VM. Once created it lives ++ * for the life of the VM. Closing the file descriptor only drops our ++ * reference to it and the device's reference to kvm. Therefore once ++ * initialized, this file descriptor is only released on QEMU exit and ++ * we'll re-use it should another vfio device be attached before then. ++ */ ++static int vfio_kvm_device_fd = -1; ++ + static void vfio_disable_interrupts(VFIODevice *vdev); + static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len); + static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, +@@ -3033,6 +3042,59 @@ static void vfio_pci_reset_handler(void *opaque) + } + } + ++static void vfio_kvm_device_add_group(VFIOGroup *group) ++{ ++#ifdef CONFIG_KVM ++ struct kvm_device_attr attr = { ++ .group = KVM_DEV_VFIO_GROUP, ++ .attr = KVM_DEV_VFIO_GROUP_ADD, ++ .addr = (uint64_t)(unsigned long)&group->fd, ++ }; ++ ++ if (!kvm_enabled()) { ++ return; ++ } ++ ++ if (vfio_kvm_device_fd < 0) { ++ struct kvm_create_device cd = { ++ .type = KVM_DEV_TYPE_VFIO, ++ }; ++ ++ if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { ++ DPRINTF("KVM_CREATE_DEVICE: %m\n"); ++ return; ++ } ++ ++ vfio_kvm_device_fd = cd.fd; ++ } ++ ++ if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { ++ error_report("Failed to add group %d to KVM VFIO device: %m", ++ group->groupid); ++ } ++#endif ++} ++ ++static void vfio_kvm_device_del_group(VFIOGroup *group) ++{ ++#ifdef CONFIG_KVM ++ struct kvm_device_attr attr = { ++ .group = KVM_DEV_VFIO_GROUP, ++ .attr = KVM_DEV_VFIO_GROUP_DEL, ++ .addr = (uint64_t)(unsigned long)&group->fd, ++ }; ++ ++ if (vfio_kvm_device_fd < 0) { ++ return; ++ } ++ ++ if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { ++ error_report("Failed to remove group %d to KVM VFIO device: %m", ++ group->groupid); ++ } ++#endif ++} ++ + static int vfio_connect_container(VFIOGroup *group) + { + VFIOContainer *container; +@@ -3181,6 +3243,8 @@ static VFIOGroup *vfio_get_group(int groupid) + + QLIST_INSERT_HEAD(&group_list, group, next); + ++ vfio_kvm_device_add_group(group); ++ + return group; + } + +@@ -3190,6 +3254,7 @@ static void vfio_put_group(VFIOGroup *group) + return; + } + ++ vfio_kvm_device_del_group(group); + vfio_disconnect_container(group); + QLIST_REMOVE(group, next); + DPRINTF("vfio_put_group: close group->fd\n"); +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-Test-device-reset-capabilities.patch b/SOURCES/kvm-vfio-pci-Test-device-reset-capabilities.patch new file mode 100644 index 0000000..86c9d1e --- /dev/null +++ b/SOURCES/kvm-vfio-pci-Test-device-reset-capabilities.patch @@ -0,0 +1,116 @@ +From bd32da91efdbcccaeb7eb2ad06f3c87946fce903 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:37:29 +0100 +Subject: [PATCH 13/25] vfio-pci: Test device reset capabilities + +RH-Author: Alex Williamson +Message-id: <20131105153729.16057.85790.stgit@bling.home> +Patchwork-id: 55422 +O-Subject: [RHEL7 qemu-kvm PATCH 1/5] vfio-pci: Test device reset capabilities +Bugzilla: 1026550 +RH-Acked-by: Bandan Das +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +Bugzilla: 1026550 +Upstream commit: befe5176ef7a0004ba23517c97c804e292273635 + +Not all resets are created equal. PM reset is not very reliable, +especially for GPUs, so we might want to opt for a bus reset if a +standard reset will only do a D3hot->D0 transition. We can also +use this to tell if the standard reset will do a bus reset (if +neither has_pm_reset or has_flr is probed, but the device still +supports reset). + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 files changed, 46 insertions(+), 0 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index 286dad1..8e69182 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -185,6 +185,8 @@ typedef struct VFIODevice { + bool reset_works; + bool has_vga; + bool pci_aer; ++ bool has_flr; ++ bool has_pm_reset; + } VFIODevice; + + typedef struct VFIOGroup { +@@ -2508,6 +2510,42 @@ static int vfio_setup_pcie_cap(VFIODevice *vdev, int pos, uint8_t size) + return pos; + } + ++static void vfio_check_pcie_flr(VFIODevice *vdev, uint8_t pos) ++{ ++ uint32_t cap = pci_get_long(vdev->pdev.config + pos + PCI_EXP_DEVCAP); ++ ++ if (cap & PCI_EXP_DEVCAP_FLR) { ++ DPRINTF("%04x:%02x:%02x.%x Supports FLR via PCIe cap\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ vdev->has_flr = true; ++ } ++} ++ ++static void vfio_check_pm_reset(VFIODevice *vdev, uint8_t pos) ++{ ++ uint16_t csr = pci_get_word(vdev->pdev.config + pos + PCI_PM_CTRL); ++ ++ if (!(csr & PCI_PM_CTRL_NO_SOFT_RESET)) { ++ DPRINTF("%04x:%02x:%02x.%x Supports PM reset\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ vdev->has_pm_reset = true; ++ } ++} ++ ++static void vfio_check_af_flr(VFIODevice *vdev, uint8_t pos) ++{ ++ uint8_t cap = pci_get_byte(vdev->pdev.config + pos + PCI_AF_CAP); ++ ++ if ((cap & PCI_AF_CAP_TP) && (cap & PCI_AF_CAP_FLR)) { ++ DPRINTF("%04x:%02x:%02x.%x Supports FLR via AF cap\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); ++ vdev->has_flr = true; ++ } ++} ++ + static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos) + { + PCIDevice *pdev = &vdev->pdev; +@@ -2552,13 +2590,21 @@ static int vfio_add_std_cap(VFIODevice *vdev, uint8_t pos) + ret = vfio_setup_msi(vdev, pos); + break; + case PCI_CAP_ID_EXP: ++ vfio_check_pcie_flr(vdev, pos); + ret = vfio_setup_pcie_cap(vdev, pos, size); + break; + case PCI_CAP_ID_MSIX: + ret = vfio_setup_msix(vdev, pos); + break; + case PCI_CAP_ID_PM: ++ vfio_check_pm_reset(vdev, pos); + vdev->pm_cap = pos; ++ ret = pci_add_capability(pdev, cap_id, pos, size); ++ break; ++ case PCI_CAP_ID_AF: ++ vfio_check_af_flr(vdev, pos); ++ ret = pci_add_capability(pdev, cap_id, pos, size); ++ break; + default: + ret = pci_add_capability(pdev, cap_id, pos, size); + break; +-- +1.7.1 + diff --git a/SOURCES/kvm-vfio-pci-VGA-quirk-update.patch b/SOURCES/kvm-vfio-pci-VGA-quirk-update.patch new file mode 100644 index 0000000..b1c4ecc --- /dev/null +++ b/SOURCES/kvm-vfio-pci-VGA-quirk-update.patch @@ -0,0 +1,947 @@ +From 7bbd16ac0463f162e4ca38e11876bdea519a0461 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 5 Nov 2013 15:30:34 +0100 +Subject: [PATCH 11/25] vfio-pci: VGA quirk update + +RH-Author: Alex Williamson +Message-id: <20131105153034.15749.72694.stgit@bling.home> +Patchwork-id: 55414 +O-Subject: [RHEL7 qemu-kvm PATCH v2 1/2] vfio-pci: VGA quirk update +Bugzilla: 1025477 +RH-Acked-by: Bandan Das +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Paolo Bonzini + +Bugzilla: 1025477 +Upstream commit: 39360f0b91d38790b5756d621ca9a7dd93ca8816 + +Turns out all the suspicions for AMD devices were correct, everywhere +we read a BAR address that the address matches the config space offset, +there's full access to PCI config space. Attempt to generalize some +helpers to allow quirks to easily be added for mirrors and windows. +Also fill in complete config space for AMD. + +Signed-off-by: Alex Williamson +--- + hw/misc/vfio.c | 657 +++++++++++++++++++++++++++----------------------------- + 1 file changed, 321 insertions(+), 336 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/misc/vfio.c | 657 +++++++++++++++++++++++++++----------------------------- + 1 files changed, 321 insertions(+), 336 deletions(-) + +diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c +index a966c58..a072fd9 100644 +--- a/hw/misc/vfio.c ++++ b/hw/misc/vfio.c +@@ -59,8 +59,23 @@ typedef struct VFIOQuirk { + MemoryRegion mem; + struct VFIODevice *vdev; + QLIST_ENTRY(VFIOQuirk) next; +- uint32_t data; +- uint32_t data2; ++ struct { ++ uint32_t base_offset:TARGET_PAGE_BITS; ++ uint32_t address_offset:TARGET_PAGE_BITS; ++ uint32_t address_size:3; ++ uint32_t bar:3; ++ ++ uint32_t address_match; ++ uint32_t address_mask; ++ ++ uint32_t address_val:TARGET_PAGE_BITS; ++ uint32_t data_offset:TARGET_PAGE_BITS; ++ uint32_t data_size:3; ++ ++ uint8_t flags; ++ uint8_t read_flags; ++ uint8_t write_flags; ++ } data; + } VFIOQuirk; + + typedef struct VFIOBAR { +@@ -72,6 +87,8 @@ typedef struct VFIOBAR { + size_t size; + uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ + uint8_t nr; /* cache the BAR number for debug */ ++ bool ioport; ++ bool mem64; + QLIST_HEAD(, VFIOQuirk) quirks; + } VFIOBAR; + +@@ -1099,251 +1116,315 @@ static const MemoryRegionOps vfio_vga_ops = { + * Device specific quirks + */ + +-#define PCI_VENDOR_ID_ATI 0x1002 ++/* Is range1 fully contained within range2? */ ++static bool vfio_range_contained(uint64_t first1, uint64_t len1, ++ uint64_t first2, uint64_t len2) { ++ return (first1 >= first2 && first1 + len1 <= first2 + len2); ++} + +-/* +- * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon +- * HD 5450/6350]) reports the upper byte of the physical address of the +- * I/O port BAR4 through VGA register 0x3c3. The BAR is 256 bytes, so the +- * lower byte is known to be zero. Probing for this quirk reads 0xff from +- * port 0x3c3 on some devices so we store the physical address and replace +- * reads with the virtual address any time it matches. XXX Research when +- * to enable quirk. +- */ +-static uint64_t vfio_ati_3c3_quirk_read(void *opaque, +- hwaddr addr, unsigned size) ++static bool vfio_flags_enabled(uint8_t flags, uint8_t mask) ++{ ++ return (mask && (flags & mask) == mask); ++} ++ ++static uint64_t vfio_generic_window_quirk_read(void *opaque, ++ hwaddr addr, unsigned size) + { + VFIOQuirk *quirk = opaque; + VFIODevice *vdev = quirk->vdev; +- PCIDevice *pdev = &vdev->pdev; +- uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], +- addr + 0x3, size); ++ uint64_t data; + +- if (data == quirk->data) { +- data = pci_get_byte(pdev->config + PCI_BASE_ADDRESS_4 + 1); +- DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data); ++ if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && ++ ranges_overlap(addr, size, ++ quirk->data.data_offset, quirk->data.data_size)) { ++ hwaddr offset = addr - quirk->data.data_offset; ++ ++ if (!vfio_range_contained(addr, size, quirk->data.data_offset, ++ quirk->data.data_size)) { ++ hw_error("%s: window data read not fully contained: %s\n", ++ __func__, memory_region_name(&quirk->mem)); ++ } ++ ++ data = vfio_pci_read_config(&vdev->pdev, ++ quirk->data.address_val + offset, size); ++ ++ DPRINTF("%s read(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", %d) = 0x%" ++ PRIx64"\n", memory_region_name(&quirk->mem), vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function, ++ quirk->data.bar, addr, size, data); ++ } else { ++ data = vfio_bar_read(&vdev->bars[quirk->data.bar], ++ addr + quirk->data.base_offset, size); + } + + return data; + } + +-static const MemoryRegionOps vfio_ati_3c3_quirk = { +- .read = vfio_ati_3c3_quirk_read, +- .endianness = DEVICE_LITTLE_ENDIAN, +-}; +- +-static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev) ++static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr, ++ uint64_t data, unsigned size) + { +- PCIDevice *pdev = &vdev->pdev; +- off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_4; +- uint32_t physbar; +- VFIOQuirk *quirk; ++ VFIOQuirk *quirk = opaque; ++ VFIODevice *vdev = quirk->vdev; + +- if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI || +- vdev->bars[4].size < 256) { +- return; +- } ++ if (ranges_overlap(addr, size, ++ quirk->data.address_offset, quirk->data.address_size)) { + +- /* Get I/O port BAR physical address */ +- if (pread(vdev->fd, &physbar, 4, physoffset) != 4) { +- error_report("vfio: probe failed for ATI/AMD 0x3c3 quirk on device " +- "%04x:%02x:%02x.%x", vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function); +- return; ++ if (addr != quirk->data.address_offset) { ++ hw_error("%s: offset write into address window: %s\n", ++ __func__, memory_region_name(&quirk->mem)); ++ } ++ ++ if ((data & ~quirk->data.address_mask) == quirk->data.address_match) { ++ quirk->data.flags |= quirk->data.write_flags | ++ quirk->data.read_flags; ++ quirk->data.address_val = data & quirk->data.address_mask; ++ } else { ++ quirk->data.flags &= ~(quirk->data.write_flags | ++ quirk->data.read_flags); ++ } + } + +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->vdev = vdev; +- quirk->data = (physbar >> 8) & 0xff; ++ if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && ++ ranges_overlap(addr, size, ++ quirk->data.data_offset, quirk->data.data_size)) { ++ hwaddr offset = addr - quirk->data.data_offset; + +- memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk, +- "vfio-ati-3c3-quirk", 1); +- memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3, +- &quirk->mem); ++ if (!vfio_range_contained(addr, size, quirk->data.data_offset, ++ quirk->data.data_size)) { ++ hw_error("%s: window data write not fully contained: %s\n", ++ __func__, memory_region_name(&quirk->mem)); ++ } + +- QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, +- quirk, next); ++ vfio_pci_write_config(&vdev->pdev, ++ quirk->data.address_val + offset, data, size); ++ DPRINTF("%s write(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%" ++ PRIx64", %d)\n", memory_region_name(&quirk->mem), ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function, quirk->data.bar, addr, data, size); ++ return; ++ } + +- DPRINTF("Enabled ATI/AMD quirk 0x3c3 for device %04x:%02x:%02x.%x\n", +- vdev->host.domain, vdev->host.bus, vdev->host.slot, +- vdev->host.function); ++ vfio_bar_write(&vdev->bars[quirk->data.bar], ++ addr + quirk->data.base_offset, data, size); + } + +-/* +- * Device 1002:68f9 (Advanced Micro Devices [AMD] nee ATI Cedar PRO [Radeon +- * HD 5450/6350]) reports the physical address of MMIO BAR0 through a +- * write/read operation on I/O port BAR4. When uint32_t 0x4010 is written +- * to offset 0x0, the subsequent read from offset 0x4 returns the contents +- * of BAR0. Test for this quirk on all ATI/AMD devices. XXX - Note that +- * 0x10 is the offset of BAR0 in config sapce, is this a window to all of +- * config space? +- */ +-static uint64_t vfio_ati_4010_quirk_read(void *opaque, +- hwaddr addr, unsigned size) ++static const MemoryRegionOps vfio_generic_window_quirk = { ++ .read = vfio_generic_window_quirk_read, ++ .write = vfio_generic_window_quirk_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static uint64_t vfio_generic_quirk_read(void *opaque, ++ hwaddr addr, unsigned size) + { + VFIOQuirk *quirk = opaque; + VFIODevice *vdev = quirk->vdev; +- PCIDevice *pdev = &vdev->pdev; +- uint64_t data = vfio_bar_read(&vdev->bars[4], addr, size); ++ hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; ++ hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; ++ uint64_t data; + +- if (addr == 4 && size == 4 && quirk->data) { +- data = pci_get_long(pdev->config + PCI_BASE_ADDRESS_0); +- DPRINTF("%s(BAR4+0x4) = 0x%"PRIx64"\n", __func__, data); +- } ++ if (vfio_flags_enabled(quirk->data.flags, quirk->data.read_flags) && ++ ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { ++ if (!vfio_range_contained(addr, size, offset, ++ quirk->data.address_mask + 1)) { ++ hw_error("%s: read not fully contained: %s\n", ++ __func__, memory_region_name(&quirk->mem)); ++ } + +- quirk->data = 0; ++ data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); ++ ++ DPRINTF("%s read(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", %d) = 0x%" ++ PRIx64"\n", memory_region_name(&quirk->mem), vdev->host.domain, ++ vdev->host.bus, vdev->host.slot, vdev->host.function, ++ quirk->data.bar, addr + base, size, data); ++ } else { ++ data = vfio_bar_read(&vdev->bars[quirk->data.bar], addr + base, size); ++ } + + return data; + } + +-static void vfio_ati_4010_quirk_write(void *opaque, hwaddr addr, +- uint64_t data, unsigned size) ++static void vfio_generic_quirk_write(void *opaque, hwaddr addr, ++ uint64_t data, unsigned size) + { + VFIOQuirk *quirk = opaque; + VFIODevice *vdev = quirk->vdev; ++ hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK; ++ hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK; ++ ++ if (vfio_flags_enabled(quirk->data.flags, quirk->data.write_flags) && ++ ranges_overlap(addr, size, offset, quirk->data.address_mask + 1)) { ++ if (!vfio_range_contained(addr, size, offset, ++ quirk->data.address_mask + 1)) { ++ hw_error("%s: write not fully contained: %s\n", ++ __func__, memory_region_name(&quirk->mem)); ++ } + +- vfio_bar_write(&vdev->bars[4], addr, data, size); ++ vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); + +- quirk->data = (addr == 0 && size == 4 && data == 0x4010) ? 1 : 0; ++ DPRINTF("%s write(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%" ++ PRIx64", %d)\n", memory_region_name(&quirk->mem), ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function, quirk->data.bar, addr + base, data, size); ++ } else { ++ vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size); ++ } + } + +-static const MemoryRegionOps vfio_ati_4010_quirk = { +- .read = vfio_ati_4010_quirk_read, +- .write = vfio_ati_4010_quirk_write, ++static const MemoryRegionOps vfio_generic_quirk = { ++ .read = vfio_generic_quirk_read, ++ .write = vfio_generic_quirk_write, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + +-static void vfio_probe_ati_4010_quirk(VFIODevice *vdev, int nr) ++#define PCI_VENDOR_ID_ATI 0x1002 ++ ++/* ++ * Radeon HD cards (HD5450 & HD7850) report the upper byte of the I/O port BAR ++ * through VGA register 0x3c3. On newer cards, the I/O port BAR is always ++ * BAR4 (older cards like the X550 used BAR1, but we don't care to support ++ * those). Note that on bare metal, a read of 0x3c3 doesn't always return the ++ * I/O port BAR address. Originally this was coded to return the virtual BAR ++ * address only if the physical register read returns the actual BAR address, ++ * but users have reported greater success if we return the virtual address ++ * unconditionally. ++ */ ++static uint64_t vfio_ati_3c3_quirk_read(void *opaque, ++ hwaddr addr, unsigned size) ++{ ++ VFIOQuirk *quirk = opaque; ++ VFIODevice *vdev = quirk->vdev; ++ uint64_t data = vfio_pci_read_config(&vdev->pdev, ++ PCI_BASE_ADDRESS_0 + (4 * 4) + 1, ++ size); ++ DPRINTF("%s(0x3c3, 1) = 0x%"PRIx64"\n", __func__, data); ++ ++ return data; ++} ++ ++static const MemoryRegionOps vfio_ati_3c3_quirk = { ++ .read = vfio_ati_3c3_quirk_read, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev) + { + PCIDevice *pdev = &vdev->pdev; +- off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0; +- uint32_t physbar0; +- uint64_t data; + VFIOQuirk *quirk; + +- if (!vdev->has_vga || nr != 4 || !vdev->bars[0].size || +- pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { +- return; +- } +- +- /* Get I/O port BAR physical address */ +- if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) { +- error_report("vfio: probe failed for ATI/AMD 0x4010 quirk on device " +- "%04x:%02x:%02x.%x", vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function); ++ if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { + return; + } + +- /* Write 0x4010 to I/O port BAR offset 0 */ +- vfio_bar_write(&vdev->bars[4], 0, 0x4010, 4); +- /* Read back result */ +- data = vfio_bar_read(&vdev->bars[4], 4, 4); +- +- /* If the register matches the physical address of BAR0, we need a quirk */ +- if (data != physbar0) { ++ /* ++ * As long as the BAR is >= 256 bytes it will be aligned such that the ++ * lower byte is always zero. Filter out anything else, if it exists. ++ */ ++ if (!vdev->bars[4].ioport || vdev->bars[4].size < 256) { + return; + } + + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; + +- memory_region_init_io(&quirk->mem, &vfio_ati_4010_quirk, quirk, +- "vfio-ati-4010-quirk", 8); +- memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); ++ memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk, ++ "vfio-ati-3c3-quirk", 1); ++ memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, ++ 3 /* offset 3 bytes from 0x3c0 */, &quirk->mem); + +- QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++ QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, ++ quirk, next); + +- DPRINTF("Enabled ATI/AMD quirk 0x4010 for device %04x:%02x:%02x.%x\n", ++ DPRINTF("Enabled ATI/AMD quirk 0x3c3 BAR4for device %04x:%02x:%02x.%x\n", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + } + + /* +- * Device 1002:5b63 (Advanced Micro Devices [AMD] nee ATI RV370 [Radeon X550]) +- * retrieves the upper half of the MMIO BAR0 physical address by writing +- * 0xf10 to I/O port BAR1 offset 0 and reading the result from offset 6. +- * XXX - 0x10 is the offset of BAR0 in PCI config space, this could provide +- * full access to config space. Config space is little endian, so the data +- * register probably starts at 0x4. ++ * Newer ATI/AMD devices, including HD5450 and HD7850, have a window to PCI ++ * config space through MMIO BAR2 at offset 0x4000. Nothing seems to access ++ * the MMIO space directly, but a window to this space is provided through ++ * I/O port BAR4. Offset 0x0 is the address register and offset 0x4 is the ++ * data register. When the address is programmed to a range of 0x4000-0x4fff ++ * PCI configuration space is available. Experimentation seems to indicate ++ * that only read-only access is provided, but we drop writes when the window ++ * is enabled to config space nonetheless. + */ +-static uint64_t vfio_ati_f10_quirk_read(void *opaque, +- hwaddr addr, unsigned size) ++static void vfio_probe_ati_bar4_window_quirk(VFIODevice *vdev, int nr) + { +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; + PCIDevice *pdev = &vdev->pdev; +- uint64_t data = vfio_bar_read(&vdev->bars[1], addr, size); ++ VFIOQuirk *quirk; + +- if (addr == 6 && size == 2 && quirk->data) { +- data = pci_get_word(pdev->config + PCI_BASE_ADDRESS_0 + 2); +- DPRINTF("%s(BAR1+0x6) = 0x%"PRIx64"\n", __func__, data); ++ if (!vdev->has_vga || nr != 4 || ++ pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { ++ return; + } + +- quirk->data = 0; +- +- return data; +-} +- +-static void vfio_ati_f10_quirk_write(void *opaque, hwaddr addr, +- uint64_t data, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->vdev = vdev; ++ quirk->data.address_size = 4; ++ quirk->data.data_offset = 4; ++ quirk->data.data_size = 4; ++ quirk->data.address_match = 0x4000; ++ quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; ++ quirk->data.bar = nr; ++ quirk->data.read_flags = quirk->data.write_flags = 1; ++ ++ memory_region_init_io(&quirk->mem, ++ &vfio_generic_window_quirk, quirk, ++ "vfio-ati-bar4-window-quirk", 8); ++ memory_region_add_subregion_overlap(&vdev->bars[nr].mem, ++ quirk->data.base_offset, &quirk->mem, 1); + +- vfio_bar_write(&vdev->bars[1], addr, data, size); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + +- quirk->data = (addr == 0 && size == 4 && data == 0xf10) ? 1 : 0; ++ DPRINTF("Enabled ATI/AMD BAR4 window quirk for device %04x:%02x:%02x.%x\n", ++ vdev->host.domain, vdev->host.bus, vdev->host.slot, ++ vdev->host.function); + } + +-static const MemoryRegionOps vfio_ati_f10_quirk = { +- .read = vfio_ati_f10_quirk_read, +- .write = vfio_ati_f10_quirk_write, +- .endianness = DEVICE_LITTLE_ENDIAN, +-}; +- +-static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr) ++/* ++ * Trap the BAR2 MMIO window to config space as well. ++ */ ++static void vfio_probe_ati_bar2_4000_quirk(VFIODevice *vdev, int nr) + { + PCIDevice *pdev = &vdev->pdev; +- off_t physoffset = vdev->config_offset + PCI_BASE_ADDRESS_0; +- uint32_t physbar0; +- uint64_t data; + VFIOQuirk *quirk; + +- if (!vdev->has_vga || nr != 1 || !vdev->bars[0].size || ++ /* Only enable on newer devices where BAR2 is 64bit */ ++ if (!vdev->has_vga || nr != 2 || !vdev->bars[2].mem64 || + pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) { + return; + } + +- /* Get I/O port BAR physical address */ +- if (pread(vdev->fd, &physbar0, 4, physoffset) != 4) { +- error_report("vfio: probe failed for ATI/AMD 0xf10 quirk on device " +- "%04x:%02x:%02x.%x", vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function); +- return; +- } +- +- vfio_bar_write(&vdev->bars[1], 0, 0xf10, 4); +- data = vfio_bar_read(&vdev->bars[1], 0x6, 2); +- +- /* If the register matches the physical address of BAR0, we need a quirk */ +- if (data != (le32_to_cpu(physbar0) >> 16)) { +- return; +- } +- + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; +- +- memory_region_init_io(&quirk->mem, &vfio_ati_f10_quirk, quirk, +- "vfio-ati-f10-quirk", 8); +- memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); ++ quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; ++ quirk->data.address_match = 0x4000; ++ quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; ++ quirk->data.bar = nr; ++ ++ memory_region_init_io(&quirk->mem, &vfio_generic_quirk, quirk, ++ "vfio-ati-bar2-4000-quirk", ++ TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); ++ memory_region_add_subregion_overlap(&vdev->bars[nr].mem, ++ quirk->data.address_match & TARGET_PAGE_MASK, ++ &quirk->mem, 1); + + QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + +- DPRINTF("Enabled ATI/AMD quirk 0xf10 for device %04x:%02x:%02x.%x\n", ++ DPRINTF("Enabled ATI/AMD BAR2 0x4000 quirk for device %04x:%02x:%02x.%x\n", + vdev->host.domain, vdev->host.bus, vdev->host.slot, + vdev->host.function); + } + ++/* ++ * Older ATI/AMD cards like the X550 have a similar window to that above. ++ * I/O port BAR1 provides a window to a mirror of PCI config space located ++ * in BAR2 at offset 0xf00. We don't care to support such older cards, but ++ * note it for future reference. ++ */ ++ + #define PCI_VENDOR_ID_NVIDIA 0x10de + + /* +@@ -1362,7 +1443,7 @@ static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr) + * that use the I/O port BAR5 window but it doesn't hurt to leave it. + */ + enum { +- NV_3D0_NONE, ++ NV_3D0_NONE = 0, + NV_3D0_SELECT, + NV_3D0_WINDOW, + NV_3D0_READ, +@@ -1376,14 +1457,14 @@ static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque, + VFIODevice *vdev = quirk->vdev; + PCIDevice *pdev = &vdev->pdev; + uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], +- addr + 0x10, size); ++ addr + quirk->data.base_offset, size); + +- if (quirk->data == NV_3D0_READ && addr == 0) { +- data = vfio_pci_read_config(pdev, quirk->data2, size); ++ if (quirk->data.flags == NV_3D0_READ && addr == quirk->data.data_offset) { ++ data = vfio_pci_read_config(pdev, quirk->data.address_val, size); + DPRINTF("%s(0x3d0, %d) = 0x%"PRIx64"\n", __func__, size, data); + } + +- quirk->data = NV_3D0_NONE; ++ quirk->data.flags = NV_3D0_NONE; + + return data; + } +@@ -1395,43 +1476,42 @@ static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr, + VFIODevice *vdev = quirk->vdev; + PCIDevice *pdev = &vdev->pdev; + +- switch (quirk->data) { ++ switch (quirk->data.flags) { + case NV_3D0_NONE: +- if (addr == 4 && data == 0x338) { +- quirk->data = NV_3D0_SELECT; ++ if (addr == quirk->data.address_offset && data == 0x338) { ++ quirk->data.flags = NV_3D0_SELECT; + } + break; + case NV_3D0_SELECT: +- quirk->data = NV_3D0_NONE; +- if (addr == 0 && (data & ~0xff) == 0x1800) { +- quirk->data = NV_3D0_WINDOW; +- quirk->data2 = data & 0xff; ++ quirk->data.flags = NV_3D0_NONE; ++ if (addr == quirk->data.data_offset && ++ (data & ~quirk->data.address_mask) == quirk->data.address_match) { ++ quirk->data.flags = NV_3D0_WINDOW; ++ quirk->data.address_val = data & quirk->data.address_mask; + } + break; + case NV_3D0_WINDOW: +- quirk->data = NV_3D0_NONE; +- if (addr == 4) { ++ quirk->data.flags = NV_3D0_NONE; ++ if (addr == quirk->data.address_offset) { + if (data == 0x538) { +- quirk->data = NV_3D0_READ; ++ quirk->data.flags = NV_3D0_READ; + } else if (data == 0x738) { +- quirk->data = NV_3D0_WRITE; ++ quirk->data.flags = NV_3D0_WRITE; + } + } + break; + case NV_3D0_WRITE: +- quirk->data = NV_3D0_NONE; +- if (addr == 0) { +- vfio_pci_write_config(pdev, quirk->data2, data, size); ++ quirk->data.flags = NV_3D0_NONE; ++ if (addr == quirk->data.data_offset) { ++ vfio_pci_write_config(pdev, quirk->data.address_val, data, size); + DPRINTF("%s(0x3d0, 0x%"PRIx64", %d)\n", __func__, data, size); + return; + } + break; +- default: +- quirk->data = NV_3D0_NONE; + } + + vfio_vga_write(&vdev->vga.region[QEMU_PCI_VGA_IO_HI], +- addr + 0x10, data, size); ++ addr + quirk->data.base_offset, data, size); + } + + static const MemoryRegionOps vfio_nvidia_3d0_quirk = { +@@ -1452,11 +1532,18 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIODevice *vdev) + + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; +- +- memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, quirk, +- "vfio-nvidia-3d0-quirk", 6); ++ quirk->data.base_offset = 0x10; ++ quirk->data.address_offset = 4; ++ quirk->data.address_size = 2; ++ quirk->data.address_match = 0x1800; ++ quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; ++ quirk->data.data_offset = 0; ++ quirk->data.data_size = 4; ++ ++ memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, ++ quirk, "vfio-nvidia-3d0-quirk", 6); + memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, +- 0x10, &quirk->mem); ++ quirk->data.base_offset, &quirk->mem); + + QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks, + quirk, next); +@@ -1480,76 +1567,46 @@ enum { + NV_BAR5_VALID = 0x7, + }; + +-static uint64_t vfio_nvidia_bar5_window_quirk_read(void *opaque, +- hwaddr addr, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; +- uint64_t data = vfio_bar_read(&vdev->bars[5], addr, size); +- +- if (addr == 0xc && quirk->data == NV_BAR5_VALID) { +- data = vfio_pci_read_config(&vdev->pdev, quirk->data2, size); +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", %d) = 0x%" +- PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, addr, size, data); +- } +- +- return data; +-} +- + static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) + { + VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; + +- /* +- * Use quirk->data to track enables and quirk->data2 for the offset +- */ + switch (addr) { + case 0x0: + if (data & 0x1) { +- quirk->data |= NV_BAR5_MASTER; ++ quirk->data.flags |= NV_BAR5_MASTER; + } else { +- quirk->data &= ~NV_BAR5_MASTER; ++ quirk->data.flags &= ~NV_BAR5_MASTER; + } + break; + case 0x4: + if (data & 0x1) { +- quirk->data |= NV_BAR5_ENABLE; ++ quirk->data.flags |= NV_BAR5_ENABLE; + } else { +- quirk->data &= ~NV_BAR5_ENABLE; ++ quirk->data.flags &= ~NV_BAR5_ENABLE; + } + break; + case 0x8: +- if (quirk->data & NV_BAR5_MASTER) { ++ if (quirk->data.flags & NV_BAR5_MASTER) { + if ((data & ~0xfff) == 0x88000) { +- quirk->data |= NV_BAR5_ADDRESS; +- quirk->data2 = data & 0xfff; ++ quirk->data.flags |= NV_BAR5_ADDRESS; ++ quirk->data.address_val = data & 0xfff; + } else if ((data & ~0xff) == 0x1800) { +- quirk->data |= NV_BAR5_ADDRESS; +- quirk->data2 = data & 0xff; ++ quirk->data.flags |= NV_BAR5_ADDRESS; ++ quirk->data.address_val = data & 0xff; + } else { +- quirk->data &= ~NV_BAR5_ADDRESS; ++ quirk->data.flags &= ~NV_BAR5_ADDRESS; + } + } + break; +- case 0xc: +- if (quirk->data == NV_BAR5_VALID) { +- vfio_pci_write_config(&vdev->pdev, quirk->data2, data, size); +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR5+0x%"HWADDR_PRIx", 0x%" +- PRIx64", %d)\n", __func__, vdev->host.domain, +- vdev->host.bus, vdev->host.slot, vdev->host.function, +- addr, data, size); +- return; +- } + } + +- vfio_bar_write(&vdev->bars[5], addr, data, size); ++ vfio_generic_window_quirk_write(opaque, addr, data, size); + } + + static const MemoryRegionOps vfio_nvidia_bar5_window_quirk = { +- .read = vfio_nvidia_bar5_window_quirk_read, ++ .read = vfio_generic_window_quirk_read, + .write = vfio_nvidia_bar5_window_quirk_write, + .valid.min_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, +@@ -1567,8 +1624,15 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr) + + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; +- +- memory_region_init_io(&quirk->mem, &vfio_nvidia_bar5_window_quirk, quirk, ++ quirk->data.read_flags = quirk->data.write_flags = NV_BAR5_VALID; ++ quirk->data.address_offset = 0x8; ++ quirk->data.address_size = 0; /* actually 4, but avoids generic code */ ++ quirk->data.data_offset = 0xc; ++ quirk->data.data_size = 4; ++ quirk->data.bar = nr; ++ ++ memory_region_init_io(&quirk->mem, ++ &vfio_nvidia_bar5_window_quirk, quirk, + "vfio-nvidia-bar5-window-quirk", 16); + memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); + +@@ -1588,51 +1652,6 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr) + * + * Here's offset 0x88000... + */ +-static uint64_t vfio_nvidia_bar0_88000_quirk_read(void *opaque, +- hwaddr addr, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; +- hwaddr base = 0x88000 & TARGET_PAGE_MASK; +- hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK; +- uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size); +- +- if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { +- data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); +- +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%" +- PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, addr + base, size, data); +- } +- +- return data; +-} +- +-static void vfio_nvidia_bar0_88000_quirk_write(void *opaque, hwaddr addr, +- uint64_t data, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; +- hwaddr base = 0x88000 & TARGET_PAGE_MASK; +- hwaddr offset = 0x88000 & ~TARGET_PAGE_MASK; +- +- if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { +- vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); +- +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%" +- PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, addr + base, data, size); +- } else { +- vfio_bar_write(&vdev->bars[0], addr + base, data, size); +- } +-} +- +-static const MemoryRegionOps vfio_nvidia_bar0_88000_quirk = { +- .read = vfio_nvidia_bar0_88000_quirk_read, +- .write = vfio_nvidia_bar0_88000_quirk_write, +- .endianness = DEVICE_LITTLE_ENDIAN, +-}; +- + static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) + { + PCIDevice *pdev = &vdev->pdev; +@@ -1645,13 +1664,17 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) + + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; +- +- memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_88000_quirk, quirk, +- "vfio-nvidia-bar0-88000-quirk", +- TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE)); ++ quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; ++ quirk->data.address_match = 0x88000; ++ quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1; ++ quirk->data.bar = nr; ++ ++ memory_region_init_io(&quirk->mem, &vfio_generic_quirk, ++ quirk, "vfio-nvidia-bar0-88000-quirk", ++ TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); + memory_region_add_subregion_overlap(&vdev->bars[nr].mem, +- 0x88000 & TARGET_PAGE_MASK, +- &quirk->mem, 1); ++ quirk->data.address_match & TARGET_PAGE_MASK, ++ &quirk->mem, 1); + + QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + +@@ -1663,51 +1686,6 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) + /* + * And here's the same for BAR0 offset 0x1800... + */ +-static uint64_t vfio_nvidia_bar0_1800_quirk_read(void *opaque, +- hwaddr addr, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; +- hwaddr base = 0x1800 & TARGET_PAGE_MASK; +- hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK; +- uint64_t data = vfio_bar_read(&vdev->bars[0], addr + base, size); +- +- if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { +- data = vfio_pci_read_config(&vdev->pdev, addr - offset, size); +- +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", %d) = 0x%" +- PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, addr + base, size, data); +- } +- +- return data; +-} +- +-static void vfio_nvidia_bar0_1800_quirk_write(void *opaque, hwaddr addr, +- uint64_t data, unsigned size) +-{ +- VFIOQuirk *quirk = opaque; +- VFIODevice *vdev = quirk->vdev; +- hwaddr base = 0x1800 & TARGET_PAGE_MASK; +- hwaddr offset = 0x1800 & ~TARGET_PAGE_MASK; +- +- if (ranges_overlap(addr, size, offset, PCI_CONFIG_SPACE_SIZE)) { +- vfio_pci_write_config(&vdev->pdev, addr - offset, data, size); +- +- DPRINTF("%s(%04x:%02x:%02x.%x:BAR0+0x%"HWADDR_PRIx", 0x%" +- PRIx64", %d)\n", __func__, vdev->host.domain, vdev->host.bus, +- vdev->host.slot, vdev->host.function, addr + base, data, size); +- } else { +- vfio_bar_write(&vdev->bars[0], addr + base, data, size); +- } +-} +- +-static const MemoryRegionOps vfio_nvidia_bar0_1800_quirk = { +- .read = vfio_nvidia_bar0_1800_quirk_read, +- .write = vfio_nvidia_bar0_1800_quirk_write, +- .endianness = DEVICE_LITTLE_ENDIAN, +-}; +- + static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr) + { + PCIDevice *pdev = &vdev->pdev; +@@ -1724,13 +1702,17 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr) + + quirk = g_malloc0(sizeof(*quirk)); + quirk->vdev = vdev; ++ quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1; ++ quirk->data.address_match = 0x1800; ++ quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1; ++ quirk->data.bar = nr; + +- memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_1800_quirk, quirk, ++ memory_region_init_io(&quirk->mem, &vfio_generic_quirk, quirk, + "vfio-nvidia-bar0-1800-quirk", +- TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE)); ++ TARGET_PAGE_ALIGN(quirk->data.address_mask + 1)); + memory_region_add_subregion_overlap(&vdev->bars[nr].mem, +- 0x1800 & TARGET_PAGE_MASK, +- &quirk->mem, 1); ++ quirk->data.address_match & TARGET_PAGE_MASK, ++ &quirk->mem, 1); + + QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); + +@@ -1770,8 +1752,8 @@ static void vfio_vga_quirk_teardown(VFIODevice *vdev) + + static void vfio_bar_quirk_setup(VFIODevice *vdev, int nr) + { +- vfio_probe_ati_4010_quirk(vdev, nr); +- vfio_probe_ati_f10_quirk(vdev, nr); ++ vfio_probe_ati_bar4_window_quirk(vdev, nr); ++ vfio_probe_ati_bar2_4000_quirk(vdev, nr); + vfio_probe_nvidia_bar5_window_quirk(vdev, nr); + vfio_probe_nvidia_bar0_88000_quirk(vdev, nr); + vfio_probe_nvidia_bar0_1800_quirk(vdev, nr); +@@ -2267,11 +2249,14 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) + } + + pci_bar = le32_to_cpu(pci_bar); +- type = pci_bar & (pci_bar & PCI_BASE_ADDRESS_SPACE_IO ? +- ~PCI_BASE_ADDRESS_IO_MASK : ~PCI_BASE_ADDRESS_MEM_MASK); ++ bar->ioport = (pci_bar & PCI_BASE_ADDRESS_SPACE_IO); ++ bar->mem64 = bar->ioport ? 0 : (pci_bar & PCI_BASE_ADDRESS_MEM_TYPE_64); ++ type = pci_bar & (bar->ioport ? ~PCI_BASE_ADDRESS_IO_MASK : ++ ~PCI_BASE_ADDRESS_MEM_MASK); + + /* A "slow" read/write mapping underlies all BARs */ +- memory_region_init_io(&bar->mem, &vfio_bar_ops, bar, name, size); ++ memory_region_init_io(&bar->mem, &vfio_bar_ops, ++ bar, name, size); + pci_register_bar(&vdev->pdev, nr, type, &bar->mem); + + /* +-- +1.7.1 + diff --git a/SOURCES/kvm-virtio-blk-do-not-relay-a-previous-driver-s-WCE-conf.patch b/SOURCES/kvm-virtio-blk-do-not-relay-a-previous-driver-s-WCE-conf.patch new file mode 100644 index 0000000..8d34029 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-do-not-relay-a-previous-driver-s-WCE-conf.patch @@ -0,0 +1,126 @@ +From 20180f303f6fd602ca8fd66bdd746916184177de Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 23 Sep 2013 17:08:02 +0200 +Subject: [PATCH 04/29] virtio-blk: do not relay a previous driver's WCE configuration to the current + +RH-Author: Paolo Bonzini +Message-id: <1379956082-3646-3-git-send-email-pbonzini@redhat.com> +Patchwork-id: 54492 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 2/2] virtio-blk: do not relay a previous driver's WCE configuration to the current +Bugzilla: 1009993 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Fam Zheng +RH-Acked-by: Kevin Wolf + +The following sequence happens: +- the SeaBIOS virtio-blk driver does not support the WCE feature, which +causes QEMU to disable writeback caching + +- the Linux virtio-blk driver resets the device, finds WCE is available +but writeback caching is disabled; tells block layer to not send cache +flush commands + +- the Linux virtio-blk driver sets the DRIVER_OK bit, which causes +writeback caching to be re-enabled, but the Linux virtio-blk driver does +not know of this side effect and cache flushes remain disabled + +The bug is at the third step. If the guest does know about CONFIG_WCE, +QEMU should ignore the WCE feature's state. The guest will control the +cache mode solely using configuration space. This change makes Linux +do flushes correctly, but Linux will keep SeaBIOS's writethrough mode. + +Hence, whenever the guest is reset, the cache mode of the disk should +be reset to whatever was specified in the "-drive" option. With this +change, the Linux virtio-blk driver finds that writeback caching is +enabled, and tells the block layer to send cache flush commands +appropriately. + +Reported-by: Rusty Russell +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit ef5bc96268ceec64769617dc53b0ac3a20ff351c) +--- + hw/block/virtio-blk.c | 24 ++++++++++++++++++++++-- + include/hw/virtio/virtio-blk.h | 1 + + 2 files changed, 23 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/block/virtio-blk.c | 24 ++++++++++++++++++++++-- + include/hw/virtio/virtio-blk.h | 1 + + 2 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index cca0c77..ce1a523 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -460,9 +460,9 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, + + static void virtio_blk_reset(VirtIODevice *vdev) + { +-#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + VirtIOBlock *s = VIRTIO_BLK(vdev); + ++#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + if (s->dataplane) { + virtio_blk_data_plane_stop(s->dataplane); + } +@@ -473,6 +473,7 @@ static void virtio_blk_reset(VirtIODevice *vdev) + * are per-device request lists. + */ + bdrv_drain_all(); ++ bdrv_set_enable_write_cache(s->bs, s->original_wce); + } + + /* coalesce internal state, copy to pci i/o region 0 +@@ -564,7 +565,25 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) + } + + features = vdev->guest_features; +- bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE))); ++ ++ /* A guest that supports VIRTIO_BLK_F_CONFIG_WCE must be able to send ++ * cache flushes. Thus, the "auto writethrough" behavior is never ++ * necessary for guests that support the VIRTIO_BLK_F_CONFIG_WCE feature. ++ * Leaving it enabled would break the following sequence: ++ * ++ * Guest started with "-drive cache=writethrough" ++ * Guest sets status to 0 ++ * Guest sets DRIVER bit in status field ++ * Guest reads host features (WCE=0, CONFIG_WCE=1) ++ * Guest writes guest features (WCE=0, CONFIG_WCE=1) ++ * Guest writes 1 to the WCE configuration field (writeback mode) ++ * Guest sets DRIVER_OK bit in status field ++ * ++ * s->bs would erroneously be placed in writethrough mode. ++ */ ++ if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) { ++ bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE))); ++ } + } + + static void virtio_blk_save(QEMUFile *f, void *opaque) +@@ -674,6 +693,7 @@ static int virtio_blk_device_init(VirtIODevice *vdev) + } + + blkconf_serial(&blk->conf, &blk->serial); ++ s->original_wce = bdrv_enable_write_cache(blk->conf.bs); + if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) { + return -1; + } +diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h +index b87cf49..41885da 100644 +--- a/include/hw/virtio/virtio-blk.h ++++ b/include/hw/virtio/virtio-blk.h +@@ -123,6 +123,7 @@ typedef struct VirtIOBlock { + BlockConf *conf; + VirtIOBlkConf blk; + unsigned short sector_mask; ++ bool original_wce; + VMChangeStateEntry *change; + #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + Notifier migration_state_notifier; +-- +1.7.1 + diff --git a/SOURCES/kvm-virtio-net-fix-up-HMP-NIC-info-string-on-reset.patch b/SOURCES/kvm-virtio-net-fix-up-HMP-NIC-info-string-on-reset.patch new file mode 100644 index 0000000..b2832cd --- /dev/null +++ b/SOURCES/kvm-virtio-net-fix-up-HMP-NIC-info-string-on-reset.patch @@ -0,0 +1,48 @@ +From 418947bb253989027df4db46253287436792abd9 Mon Sep 17 00:00:00 2001 +From: Amos Kong +Date: Tue, 5 Nov 2013 09:17:42 +0100 +Subject: [PATCH 10/25] virtio-net: fix up HMP NIC info string on reset + +RH-Author: Amos Kong +Message-id: <1383643062-1844-5-git-send-email-akong@redhat.com> +Patchwork-id: 55371 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 4/4] virtio-net: fix up HMP NIC info string on reset +Bugzilla: 1026689 +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Alex Williamson +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +From: Michael S. Tsirkin + +Bugzilla: 1026689 + +When mac is updated on reset, info string has stale data. +Fix it up. + +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 702d66a813dd84afd7c3d1ad8cbdcc8e3449bcd9) +--- + hw/net/virtio-net.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/net/virtio-net.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 9ebcdfe..3290013 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -213,6 +213,7 @@ static void virtio_net_reset(VirtIODevice *vdev) + n->mac_table.uni_overflow = 0; + memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); + memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac)); ++ qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); + memset(n->vlans, 0, MAX_VLAN >> 3); + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-virtio-scsi-Make-type-virtio-scsi-common-abstract.patch b/SOURCES/kvm-virtio-scsi-Make-type-virtio-scsi-common-abstract.patch new file mode 100644 index 0000000..146a021 --- /dev/null +++ b/SOURCES/kvm-virtio-scsi-Make-type-virtio-scsi-common-abstract.patch @@ -0,0 +1,51 @@ +From 767b0e7534e7d0af6090c105f0d093461d5ea03a Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 18 Sep 2013 10:39:19 +0200 +Subject: [PATCH 26/29] virtio-scsi: Make type virtio-scsi-common abstract + +RH-Author: Miroslav Rezanina +Message-id: +Patchwork-id: 54440 +O-Subject: [RHEL7 qemu-kvm PATCH] virtio-scsi: Make type virtio-scsi-common abstract +Bugzilla: 903918 +RH-Acked-by: Markus Armbruster +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini + +From: Markus Armbruster + +BZ: 903918 +Brewbuild: https://brewweb.devel.redhat.com/taskinfo?taskID=6298357 + +It's the abstract base of virtio-scsi-device and vhost-scsi. + +Signed-off-by: Markus Armbruster +Signed-off-by: Paolo Bonzini +(cherry picked from commit a27292b5d7545509bfa171922516d2033c570205) + +Clean backport +Signed-off-by: Miroslav Rezanina +--- + hw/scsi/virtio-scsi.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/scsi/virtio-scsi.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 08dd3f3..4074088 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -682,6 +682,7 @@ static const TypeInfo virtio_scsi_common_info = { + .name = TYPE_VIRTIO_SCSI_COMMON, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOSCSICommon), ++ .abstract = true, + .class_init = virtio_scsi_common_class_init, + }; + +-- +1.7.1 + diff --git a/SOURCES/kvm-vl-Clean-up-parsing-of-boot-option-argument.patch b/SOURCES/kvm-vl-Clean-up-parsing-of-boot-option-argument.patch new file mode 100644 index 0000000..d96cb41 --- /dev/null +++ b/SOURCES/kvm-vl-Clean-up-parsing-of-boot-option-argument.patch @@ -0,0 +1,176 @@ +From 5575e0aec51f40ebec46e98ec085cda053283aba Mon Sep 17 00:00:00 2001 +Message-Id: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:11 +0200 +Subject: [PATCH 01/14] vl: Clean up parsing of -boot option argument + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-2-git-send-email-armbru@redhat.com> +Patchwork-id: 54560 +O-Subject: [PATCH 7.0 qemu-kvm 01/10] vl: Clean up parsing of -boot option argument +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Commit 3d3b8303 threw in some QemuOpts parsing without replacing the +existing ad hoc parser, resulting in a confusing mess. Clean it up. + +Two user-visible changes: + +1. Invalid options are reported more nicely. Before: + + qemu: unknown boot parameter 'x' in 'x=y' + + After: + + qemu-system-x86_64: -boot x=y: Invalid parameter 'x' + +2. If -boot is given multiple times, options accumulate, just like for + -machine. Before, only options order, once and menu accumulated. + For the other ones, all but the first -boot in non-legacy syntax + got simply ignored. + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-2-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 6ef4716cecdfa1b3794c1a33edba9840e1aa6b5f) +--- + vl.c | 84 ++++++++++++++++++-------------------------------------------------- + 1 file changed, 22 insertions(+), 62 deletions(-) + +Signed-off-by: Michal Novotny +--- + vl.c | 84 ++++++++++++++++++-------------------------------------------------- + 1 file changed, 22 insertions(+), 62 deletions(-) + +diff --git a/vl.c b/vl.c +index a40ab13..a5663ad 100644 +--- a/vl.c ++++ b/vl.c +@@ -436,9 +436,10 @@ static QemuOptsList qemu_machine_opts = { + + static QemuOptsList qemu_boot_opts = { + .name = "boot-opts", ++ .implied_opt_name = "order", ++ .merge_lists = true, + .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head), + .desc = { +- /* the three names below are not used now */ + { + .name = "order", + .type = QEMU_OPT_STRING, +@@ -447,8 +448,7 @@ static QemuOptsList qemu_boot_opts = { + .type = QEMU_OPT_STRING, + }, { + .name = "menu", +- .type = QEMU_OPT_STRING, +- /* following are really used */ ++ .type = QEMU_OPT_BOOL, + }, { + .name = "splash", + .type = QEMU_OPT_STRING, +@@ -1114,7 +1114,7 @@ int qemu_boot_set(const char *boot_devices) + return boot_set_handler(boot_set_opaque, boot_devices); + } + +-static void validate_bootdevices(char *devices) ++static void validate_bootdevices(const char *devices) + { + /* We just do some generic consistency checks */ + const char *p; +@@ -3087,70 +3087,30 @@ int main(int argc, char **argv, char **envp) + break; + case QEMU_OPTION_boot: + { +- static const char * const params[] = { +- "order", "once", "menu", +- "splash", "splash-time", +- "reboot-timeout", "strict", NULL +- }; +- char buf[sizeof(boot_devices)]; + char *standard_boot_devices; +- int legacy = 0; +- +- if (!strchr(optarg, '=')) { +- legacy = 1; +- pstrcpy(buf, sizeof(buf), optarg); +- } else if (check_params(buf, sizeof(buf), params, optarg) < 0) { +- fprintf(stderr, +- "qemu: unknown boot parameter '%s' in '%s'\n", +- buf, optarg); ++ const char *order, *once; ++ ++ opts = qemu_opts_parse(qemu_find_opts("boot-opts"), ++ optarg, 1); ++ if (!opts) { + exit(1); + } + +- if (legacy || +- get_param_value(buf, sizeof(buf), "order", optarg)) { +- validate_bootdevices(buf); +- pstrcpy(boot_devices, sizeof(boot_devices), buf); ++ order = qemu_opt_get(opts, "order"); ++ if (order) { ++ validate_bootdevices(order); ++ pstrcpy(boot_devices, sizeof(boot_devices), order); + } +- if (!legacy) { +- if (get_param_value(buf, sizeof(buf), +- "once", optarg)) { +- validate_bootdevices(buf); +- standard_boot_devices = g_strdup(boot_devices); +- pstrcpy(boot_devices, sizeof(boot_devices), buf); +- qemu_register_reset(restore_boot_devices, +- standard_boot_devices); +- } +- if (get_param_value(buf, sizeof(buf), +- "menu", optarg)) { +- if (!strcmp(buf, "on")) { +- boot_menu = 1; +- } else if (!strcmp(buf, "off")) { +- boot_menu = 0; +- } else { +- fprintf(stderr, +- "qemu: invalid option value '%s'\n", +- buf); +- exit(1); +- } +- } +- if (get_param_value(buf, sizeof(buf), +- "strict", optarg)) { +- if (!strcmp(buf, "on")) { +- boot_strict = true; +- } else if (!strcmp(buf, "off")) { +- boot_strict = false; +- } else { +- fprintf(stderr, +- "qemu: invalid option value '%s'\n", +- buf); +- exit(1); +- } +- } +- if (!qemu_opts_parse(qemu_find_opts("boot-opts"), +- optarg, 0)) { +- exit(1); +- } ++ ++ once = qemu_opt_get(opts, "once"); ++ if (once) { ++ validate_bootdevices(once); ++ standard_boot_devices = g_strdup(boot_devices); ++ pstrcpy(boot_devices, sizeof(boot_devices), once); ++ qemu_register_reset(restore_boot_devices, ++ standard_boot_devices); + } ++ boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); + } + break; + case QEMU_OPTION_fda: +-- +1.7.11.7 + diff --git a/SOURCES/kvm-vl-Fix-boot-order-and-once-regressions-and-related-b.patch b/SOURCES/kvm-vl-Fix-boot-order-and-once-regressions-and-related-b.patch new file mode 100644 index 0000000..78add7e --- /dev/null +++ b/SOURCES/kvm-vl-Fix-boot-order-and-once-regressions-and-related-b.patch @@ -0,0 +1,277 @@ +From a49a3e6984fdb8562003cff96a82b2ac7d9bcc0d Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:13 +0200 +Subject: [PATCH 03/14] vl: Fix -boot order and once regressions, and related + bugs + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-4-git-send-email-armbru@redhat.com> +Patchwork-id: 54567 +O-Subject: [PATCH 7.0 qemu-kvm 03/10] vl: Fix -boot order and once regressions, and related bugs +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Option "once" sets up a different boot order just for the initial +boot. Boot order reverts back to normal on reset. Option "order" +changes the normal boot order. + +The reversal is implemented by reset handler restore_boot_devices(), +which takes the boot order to revert to as argument. +restore_boot_devices() does nothing on its first call, because that +must be the initial machine reset. On its second call, it changes the +boot order back, and unregisters itself. + +Because we register the handler right when -boot gets parsed, we can +revert to an incorrect normal boot order, and multiple -boot can +interact in funny ways. + +Here's how things work without -boot once or order: + +* boot_devices is "". + +* main() passes machine->boot_order to to machine->init(), because + boot_devices is "". machine->init() configures firmware + accordingly. For PC machines, machine->boot_order is "cad", and + pc_cmos_init() writes it to RTC CMOS, where SeaBIOS picks it up. + +Now consider -boot order=: + +* boot_devices is "". + +* -boot order= sets boot_devices to "" (no change). + +* main() passes machine->boot_order to to machine->init(), because + boot_devices is "", as above. + + Bug: -boot order= has no effect. Broken in commit e4ada29e. + +Next, consider -boot once=a: + +* boot_devices is "". + +* -boot once=a registers restore_boot_devices() with argument "", and + sets boot_devices to "a". + +* main() passes boot_devices "a" to machine->init(), which configures + firmware accordingly. For PC machines, pc_cmos_init() writes the + boot order to RTC CMOS. + +* main() calls qemu_system_reset(). This runs reset handlers. + + - restore_boot_devices() gets called with argument "". Does + nothing, because it's the first call. + +* Machine boots, boot order is "a". + +* Machine resets (e.g. monitor command). Reset handlers run. + + - restore_boot_devices() gets called with argument "". Calls + qemu_boot_set("") to reconfigure firmware. For PC machines, + pc_boot_set() writes it into RTC CMOS. Reset handler + unregistered. + + Bug: boot order reverts to "" instead of machine->boot_order. The + actual boot order depends on how firmware interprets "". Broken + in commit e4ada29e. + +Next, consider -boot once=a -boot order=c: + +* boot_devices is "". + +* -boot once=a registers restore_boot_devices() with argument "", and + sets boot_devices to "a". + +* -boot order=c sets boot_devices to "c". + +* main() passes boot_devices "c" to machine->init(), which configures + firmware accordingly. For PC machines, pc_cmos_init() writes the + boot order to RTC CMOS. + +* main() calls qemu_system_reset(). This runs reset handlers. + + - restore_boot_devices() gets called with argument "". Does + nothing, because it's the first call. + +* Machine boots, boot order is "c". + + Bug: it should be "a". I figure this has always been broken. + +* Machine resets (e.g. monitor command). Reset handlers run. + + - restore_boot_devices() gets called with argument "". Calls + qemu_boot_set("") to reconfigure firmware. For PC machines, + pc_boot_set() writes it into RTC CMOS. Reset handler + unregistered. + + Bug: boot order reverts to "" instead of "c". I figure this has + always been broken, just differently broken before commit + e4ada29e. + +Next, consider -boot once=a -boot once=b -boot once=c: + +* boot_devices is "". + +* -boot once=a registers restore_boot_devices() with argument "", and + sets boot_devices to "a". + +* -boot once=b registers restore_boot_devices() with argument "a", and + sets boot_devices to "b". + +* -boot once=c registers restore_boot_devices() with argument "b", and + sets boot_devices to "c". + +* main() passes boot_devices "c" to machine->init(), which configures + firmware accordingly. For PC machines, pc_cmos_init() writes the + boot order to RTC CMOS. + +* main() calls qemu_system_reset(). This runs reset handlers. + + - restore_boot_devices() gets called with argument "". Does + nothing, because it's the first call. + + - restore_boot_devices() gets called with argument "a". Calls + qemu_boot_set("a") to reconfigure firmware. For PC machines, + pc_boot_set() writes it into RTC CMOS. Reset handler + unregistered. + + - restore_boot_devices() gets called with argument "b". Calls + qemu_boot_set("b") to reconfigure firmware. For PC machines, + pc_boot_set() writes it into RTC CMOS. Reset handler + unregistered. + +* Machine boots, boot order is "b". + + Bug: should really be "c", because that came last, and for all other + -boot options, the last one wins. I figure this was broken some + time before commit 37905d6a, and fixed there only for a single + occurence of "once". + +* Machine resets (e.g. monitor command). Reset handlers run. + + - restore_boot_devices() gets called with argument "". Calls + qemu_boot_set("") to reconfigure firmware. For PC machines, + pc_boot_set() writes it into RTC CMOS. Reset handler + unregistered. + + Same bug as above: boot order reverts to "" instead of + machine->boot_order. + +Fix by acting upon -boot options order, once and menu only after +option parsing is complete, and the machine is known. This is how the +other -boot options work already. + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-4-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 8281abd548d840d84223e66812491918c713e56c) +--- + vl.c | 59 ++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 30 insertions(+), 29 deletions(-) + +Signed-off-by: Michal Novotny +--- + vl.c | 59 ++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 30 insertions(+), 29 deletions(-) + +diff --git a/vl.c b/vl.c +index a5663ad..1c3236c 100644 +--- a/vl.c ++++ b/vl.c +@@ -2795,7 +2795,7 @@ int main(int argc, char **argv, char **envp) + const char *icount_option = NULL; + const char *initrd_filename; + const char *kernel_filename, *kernel_cmdline; +- char boot_devices[33] = ""; ++ const char *boot_order = NULL; + DisplayState *ds; + int cyls, heads, secs, translation; + QemuOpts *hda_opts = NULL, *opts, *machine_opts; +@@ -3086,31 +3086,9 @@ int main(int argc, char **argv, char **envp) + drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS); + break; + case QEMU_OPTION_boot: +- { +- char *standard_boot_devices; +- const char *order, *once; +- +- opts = qemu_opts_parse(qemu_find_opts("boot-opts"), +- optarg, 1); +- if (!opts) { +- exit(1); +- } +- +- order = qemu_opt_get(opts, "order"); +- if (order) { +- validate_bootdevices(order); +- pstrcpy(boot_devices, sizeof(boot_devices), order); +- } +- +- once = qemu_opt_get(opts, "once"); +- if (once) { +- validate_bootdevices(once); +- standard_boot_devices = g_strdup(boot_devices); +- pstrcpy(boot_devices, sizeof(boot_devices), once); +- qemu_register_reset(restore_boot_devices, +- standard_boot_devices); +- } +- boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); ++ opts = qemu_opts_parse(qemu_find_opts("boot-opts"), optarg, 1); ++ if (!opts) { ++ exit(1); + } + break; + case QEMU_OPTION_fda: +@@ -4049,6 +4027,31 @@ int main(int argc, char **argv, char **envp) + initrd_filename = qemu_opt_get(machine_opts, "initrd"); + kernel_cmdline = qemu_opt_get(machine_opts, "append"); + ++ if (!boot_order) { ++ boot_order = machine->boot_order; ++ } ++ opts = qemu_opts_find(qemu_find_opts("boot-opts"), NULL); ++ if (opts) { ++ char *normal_boot_order; ++ const char *order, *once; ++ ++ order = qemu_opt_get(opts, "order"); ++ if (order) { ++ validate_bootdevices(order); ++ boot_order = order; ++ } ++ ++ once = qemu_opt_get(opts, "once"); ++ if (once) { ++ validate_bootdevices(once); ++ normal_boot_order = g_strdup(boot_order); ++ boot_order = once; ++ qemu_register_reset(restore_boot_devices, normal_boot_order); ++ } ++ ++ boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); ++ } ++ + if (!kernel_cmdline) { + kernel_cmdline = ""; + } +@@ -4213,9 +4216,7 @@ int main(int argc, char **argv, char **envp) + qdev_machine_init(); + + QEMUMachineInitArgs args = { .ram_size = ram_size, +- .boot_device = (boot_devices[0] == '\0') ? +- machine->boot_order : +- boot_devices, ++ .boot_device = boot_order, + .kernel_filename = kernel_filename, + .kernel_cmdline = kernel_cmdline, + .initrd_filename = initrd_filename, +-- +1.7.11.7 + diff --git a/SOURCES/kvm-vl-New-qemu_get_machine_opts.patch b/SOURCES/kvm-vl-New-qemu_get_machine_opts.patch new file mode 100644 index 0000000..c1f7165 --- /dev/null +++ b/SOURCES/kvm-vl-New-qemu_get_machine_opts.patch @@ -0,0 +1,78 @@ +From d07eaace8b57fc37cd83b958c7242d15024ee945 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Tue, 6 Aug 2013 13:17:02 +0200 +Subject: [PATCH 09/28] vl: New qemu_get_machine_opts() + +RH-Author: Markus Armbruster +Message-id: <1375795025-28674-4-git-send-email-armbru@redhat.com> +Patchwork-id: 52991 +O-Subject: [PATCH 7.0 qemu-kvm 3/6] vl: New qemu_get_machine_opts() +Bugzilla: 980782 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michal Novotny +RH-Acked-by: Orit Wasserman + +To be used in the next few commits to fix or clean up queries of +"machine" options (-machine and its sugared forms). + +Signed-off-by: Markus Armbruster +Message-id: 1372943363-24081-4-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 7f9d6e540ec4f3bf4dc3501c4a1405998c2be4e7) +--- + include/sysemu/sysemu.h | 2 ++ + vl.c | 19 +++++++++++++++++++ + 2 files changed, 21 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + include/sysemu/sysemu.h | 2 ++ + vl.c | 19 +++++++++++++++++++ + 2 files changed, 21 insertions(+), 0 deletions(-) + +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index b5e1add..3caeb66 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -185,6 +185,8 @@ char *get_boot_devices_list(size_t *size); + + DeviceState *get_boot_device(uint32_t position); + ++QemuOpts *qemu_get_machine_opts(void); ++ + bool usb_enabled(bool default_usb); + + extern QemuOptsList qemu_drive_opts; +diff --git a/vl.c b/vl.c +index b8a7f18..fe58eff 100644 +--- a/vl.c ++++ b/vl.c +@@ -518,6 +518,25 @@ static QemuOptsList qemu_realtime_opts = { + }, + }; + ++/** ++ * Get machine options ++ * ++ * Returns: machine options (never null). ++ */ ++QemuOpts *qemu_get_machine_opts(void) ++{ ++ QemuOptsList *list; ++ QemuOpts *opts; ++ ++ list = qemu_find_opts("machine"); ++ assert(list); ++ opts = qemu_opts_find(list, NULL); ++ if (!opts) { ++ opts = qemu_opts_create_nofail(list); ++ } ++ return opts; ++} ++ + const char *qemu_get_vm_name(void) + { + return qemu_name; +-- +1.7.1 + diff --git a/SOURCES/kvm-vl-Rename-boot_devices-to-boot_order-for-consistency.patch b/SOURCES/kvm-vl-Rename-boot_devices-to-boot_order-for-consistency.patch new file mode 100644 index 0000000..e356b51 --- /dev/null +++ b/SOURCES/kvm-vl-Rename-boot_devices-to-boot_order-for-consistency.patch @@ -0,0 +1,109 @@ +From 1b91244eac9251bf754626c91f7455a437f33714 Mon Sep 17 00:00:00 2001 +Message-Id: <1b91244eac9251bf754626c91f7455a437f33714.1383564115.git.minovotn@redhat.com> +In-Reply-To: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +References: <5575e0aec51f40ebec46e98ec085cda053283aba.1383564115.git.minovotn@redhat.com> +From: Markus Armbruster +Date: Fri, 27 Sep 2013 13:31:14 +0200 +Subject: [PATCH 04/14] vl: Rename *boot_devices to *boot_order, for + consistency + +RH-Author: Markus Armbruster +Message-id: <1380288680-26645-5-git-send-email-armbru@redhat.com> +Patchwork-id: 54558 +O-Subject: [PATCH 7.0 qemu-kvm 04/10] vl: Rename *boot_devices to *boot_order, for consistency +Bugzilla: 997817 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Luiz Capitulino + +From: Markus Armbruster + +Signed-off-by: Markus Armbruster +Reviewed-by: Anthony Liguori +Message-id: 1371208516-7857-5-git-send-email-armbru@redhat.com +Signed-off-by: Anthony Liguori +(cherry picked from commit 083b79c9fea0e3842f0b2b57ff0d20ab5f57084a) +--- + include/hw/hw.h | 4 ++-- + vl.c | 16 ++++++++-------- + 2 files changed, 10 insertions(+), 10 deletions(-) + +Signed-off-by: Michal Novotny +--- + include/hw/hw.h | 4 ++-- + vl.c | 16 ++++++++-------- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/include/hw/hw.h b/include/hw/hw.h +index 1fb9afa..cc9f847 100644 +--- a/include/hw/hw.h ++++ b/include/hw/hw.h +@@ -44,9 +44,9 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); + + /* handler to set the boot_device order for a specific type of QEMUMachine */ + /* return 0 if success */ +-typedef int QEMUBootSetHandler(void *opaque, const char *boot_devices); ++typedef int QEMUBootSetHandler(void *opaque, const char *boot_order); + void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque); +-int qemu_boot_set(const char *boot_devices); ++int qemu_boot_set(const char *boot_order); + + #ifdef NEED_CPU_H + #if TARGET_LONG_BITS == 64 +diff --git a/vl.c b/vl.c +index 1c3236c..b8a8cc6 100644 +--- a/vl.c ++++ b/vl.c +@@ -1106,12 +1106,12 @@ void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque) + boot_set_opaque = opaque; + } + +-int qemu_boot_set(const char *boot_devices) ++int qemu_boot_set(const char *boot_order) + { + if (!boot_set_handler) { + return -EINVAL; + } +- return boot_set_handler(boot_set_opaque, boot_devices); ++ return boot_set_handler(boot_set_opaque, boot_order); + } + + static void validate_bootdevices(const char *devices) +@@ -1142,9 +1142,9 @@ static void validate_bootdevices(const char *devices) + } + } + +-static void restore_boot_devices(void *opaque) ++static void restore_boot_order(void *opaque) + { +- char *standard_boot_devices = opaque; ++ char *normal_boot_order = opaque; + static int first = 1; + + /* Restore boot order and remove ourselves after the first boot */ +@@ -1153,10 +1153,10 @@ static void restore_boot_devices(void *opaque) + return; + } + +- qemu_boot_set(standard_boot_devices); ++ qemu_boot_set(normal_boot_order); + +- qemu_unregister_reset(restore_boot_devices, standard_boot_devices); +- g_free(standard_boot_devices); ++ qemu_unregister_reset(restore_boot_order, normal_boot_order); ++ g_free(normal_boot_order); + } + + void add_boot_device_path(int32_t bootindex, DeviceState *dev, +@@ -4046,7 +4046,7 @@ int main(int argc, char **argv, char **envp) + validate_bootdevices(once); + normal_boot_order = g_strdup(boot_order); + boot_order = once; +- qemu_register_reset(restore_boot_devices, normal_boot_order); ++ qemu_register_reset(restore_boot_order, normal_boot_order); + } + + boot_menu = qemu_opt_get_bool(opts, "menu", boot_menu); +-- +1.7.11.7 + diff --git a/SOURCES/kvm-vl-allow-cont-from-panicked-state.patch b/SOURCES/kvm-vl-allow-cont-from-panicked-state.patch new file mode 100644 index 0000000..512884b --- /dev/null +++ b/SOURCES/kvm-vl-allow-cont-from-panicked-state.patch @@ -0,0 +1,90 @@ +From 5ef9ff360b8856803c2d9e865c3c2e83f59b1099 Mon Sep 17 00:00:00 2001 +From: Marcel Apfelbaum +Date: Wed, 6 Nov 2013 16:32:36 +0100 +Subject: [PATCH 77/81] vl: allow "cont" from panicked state + +RH-Author: Marcel Apfelbaum +Message-id: <1383755557-21590-9-git-send-email-marcel.a@redhat.com> +Patchwork-id: 55553 +O-Subject: [RHEL-7 qemu-kvm PATCH v3 8/9] vl: allow "cont" from panicked state +Bugzilla: 990601 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Alex Williamson + +From: Paolo Bonzini + +After reporting the GUEST_PANICKED monitor event, QEMU stops the VM. +The reason for this is that events are edge-triggered, and can be lost if +management dies at the wrong time. Stopping a panicked VM lets management +know of a panic even if it has crashed; management can learn about the +panic when it restarts and queries running QEMU processes. The downside +is of course that the VM will be paused while management is not running, +but that is acceptable if it only happens with explicit "-device pvpanic". + +Upon learning of a panic, management (if configured to do so) can pick a +variety of behaviors: leave the VM paused, reset it, destroy it. In +addition to all of these behaviors, it is possible to dump the VM core +from the host. + +However, right now, the panicked state is irreversible, and can only be +exited by resetting the machine. This means that any policy decision +is entirely in the hands of the host. In particular there is no way to +use the "reboot on panic" option together with pvpanic. + +This patch makes the panicked state reversible (and removes various +workarounds that were there because of the state being irreversible). +With this change, management has a wider set of possible policies: it +can just log the crash and leave policy to the guest, it can leave the +VM paused. In particular, the "log the crash and continue" is implemented +simply by sending a "cont" as soon as management learns about the panic. +Management could also implement the "irreversible paused state" itself. +And again, all such actions can be coupled with dumping the VM core. + +Unfortunately we cannot change the behavior of 1.6.0. Thus, even if +it uses "-device pvpanic", management should check for "cont" failures. +If "cont" fails, management can then log that the VM remained paused +and urge the administrator to update QEMU. + +Reviewed-by: Laszlo Ersek +Reviewed-by: Luiz Capitulino +Acked-by: Michael S. Tsirkin +Signed-off-by: Paolo Bonzini +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit df39076850958b842ac9e414dc3ab2895f1877bf) +Signed-off-by: Marcel Apfelbaum +--- + vl.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + vl.c | 5 ++--- + 1 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/vl.c b/vl.c +index 7c8ba63..9b1738b 100644 +--- a/vl.c ++++ b/vl.c +@@ -640,7 +640,7 @@ static const RunStateTransition runstate_transitions_def[] = { + { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING }, + { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE }, + +- { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED }, ++ { RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING }, + { RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE }, + + { RUN_STATE_MAX, RUN_STATE_MAX }, +@@ -687,8 +687,7 @@ int runstate_is_running(void) + bool runstate_needs_reset(void) + { + return runstate_check(RUN_STATE_INTERNAL_ERROR) || +- runstate_check(RUN_STATE_SHUTDOWN) || +- runstate_check(RUN_STATE_GUEST_PANICKED); ++ runstate_check(RUN_STATE_SHUTDOWN); + } + + StatusInfo *qmp_query_status(Error **errp) +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Fix-vmdk_parse_extents.patch b/SOURCES/kvm-vmdk-Fix-vmdk_parse_extents.patch new file mode 100644 index 0000000..3c7ec4d --- /dev/null +++ b/SOURCES/kvm-vmdk-Fix-vmdk_parse_extents.patch @@ -0,0 +1,50 @@ +From 24b35c7de7077b977ab71ccddbe004bfc4e28d82 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 7 Nov 2013 16:03:34 +0100 +Subject: [PATCH 22/25] vmdk: Fix vmdk_parse_extents + +RH-Author: Fam Zheng +Message-id: <1383795369-10623-2-git-send-email-famz@redhat.com> +Patchwork-id: 55585 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/2] vmdk: Fix vmdk_parse_extents +Bugzilla: 995866 +RH-Acked-by: Amos Kong +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +An extra 'p++' after while loop when *p == '\n' will move p to unknown +data position, risking parsing junk data or memory access violation. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 899f1ae219d5eaa96a53c996026cb0178d62a86d) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 7 +++++-- + 1 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index a3267fe..f2237cf 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -782,10 +782,13 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + extent->type = g_strdup(type); + next_line: + /* move to next line */ +- while (*p && *p != '\n') { ++ while (*p) { ++ if (*p == '\n') { ++ p++; ++ break; ++ } + p++; + } +- p++; + } + return 0; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Implement-.bdrv_has_zero_init.patch b/SOURCES/kvm-vmdk-Implement-.bdrv_has_zero_init.patch new file mode 100644 index 0000000..f37f2ff --- /dev/null +++ b/SOURCES/kvm-vmdk-Implement-.bdrv_has_zero_init.patch @@ -0,0 +1,103 @@ +From 6e011e90a93e9301c2a23a71a13f2a1664b4be2b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 13:12:58 +0100 +Subject: [PATCH 73/87] vmdk: Implement .bdrv_has_zero_init + +RH-Author: Max Reitz +Message-id: <1383756824-6921-8-git-send-email-mreitz@redhat.com> +Patchwork-id: 55562 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 07/21] vmdk: Implement .bdrv_has_zero_init +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Depending on the subformat, has_zero_init queries underlying storage for +flat extent. If it has a flat extent and its underlying storage doesn't +have zero init, return 0. Otherwise return 1. + +Aligns the operator assignments. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit da7a50f938516d0f2302965eeb82940c32028ed8) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 48 +++++++++++++++++++++++++++++++++--------------- + 1 files changed, 33 insertions(+), 15 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 213901f..bd1dd62 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1797,6 +1797,23 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) + return ret; + } + ++static int vmdk_has_zero_init(BlockDriverState *bs) ++{ ++ int i; ++ BDRVVmdkState *s = bs->opaque; ++ ++ /* If has a flat extent and its underlying storage doesn't have zero init, ++ * return 0. */ ++ for (i = 0; i < s->num_extents; i++) { ++ if (s->extents[i].flat) { ++ if (!bdrv_has_zero_init(s->extents[i].file)) { ++ return 0; ++ } ++ } ++ } ++ return 1; ++} ++ + static QEMUOptionParameter vmdk_create_options[] = { + { + .name = BLOCK_OPT_SIZE, +@@ -1835,21 +1852,22 @@ static QEMUOptionParameter vmdk_create_options[] = { + }; + + static BlockDriver bdrv_vmdk = { +- .format_name = "vmdk", +- .instance_size = sizeof(BDRVVmdkState), +- .bdrv_probe = vmdk_probe, +- .bdrv_open = vmdk_open, +- .bdrv_reopen_prepare = vmdk_reopen_prepare, +- .bdrv_read = vmdk_co_read, +- .bdrv_write = vmdk_co_write, +- .bdrv_co_write_zeroes = vmdk_co_write_zeroes, +- .bdrv_close = vmdk_close, +- .bdrv_create = vmdk_create, +- .bdrv_co_flush_to_disk = vmdk_co_flush, +- .bdrv_co_get_block_status = vmdk_co_get_block_status, +- .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, +- +- .create_options = vmdk_create_options, ++ .format_name = "vmdk", ++ .instance_size = sizeof(BDRVVmdkState), ++ .bdrv_probe = vmdk_probe, ++ .bdrv_open = vmdk_open, ++ .bdrv_reopen_prepare = vmdk_reopen_prepare, ++ .bdrv_read = vmdk_co_read, ++ .bdrv_write = vmdk_co_write, ++ .bdrv_co_write_zeroes = vmdk_co_write_zeroes, ++ .bdrv_close = vmdk_close, ++ .bdrv_create = vmdk_create, ++ .bdrv_co_flush_to_disk = vmdk_co_flush, ++ .bdrv_co_get_block_status = vmdk_co_get_block_status, ++ .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, ++ .bdrv_has_zero_init = vmdk_has_zero_init, ++ ++ .create_options = vmdk_create_options, + }; + + static void bdrv_vmdk_init(void) +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Implment-bdrv_get_specific_info.patch b/SOURCES/kvm-vmdk-Implment-bdrv_get_specific_info.patch new file mode 100644 index 0000000..71f2403 --- /dev/null +++ b/SOURCES/kvm-vmdk-Implment-bdrv_get_specific_info.patch @@ -0,0 +1,287 @@ +From 330cc46279f2fcd6f2d41d4e8beda8038c7a2fd9 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Thu, 7 Nov 2013 13:18:21 +0100 +Subject: [PATCH 87/87] vmdk: Implment bdrv_get_specific_info + +RH-Author: Max Reitz +Message-id: <1383756824-6921-22-git-send-email-mreitz@redhat.com> +Patchwork-id: 55576 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 21/21] vmdk: Implment bdrv_get_specific_info +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Implement .bdrv_get_specific_info to return the extent information. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit f4c129a38a5430b7342a7a23f53a22831154612f) + +Signed-off-by: Max Reitz +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 68 +++++++++++++++++++++++++++++++++++++++++++- + qapi-schema.json | 24 +++++++++++++++- + tests/qemu-iotests/059 | 2 +- + tests/qemu-iotests/059.out | 5 +-- + 4 files changed, 93 insertions(+), 6 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 8bef9f2..a3267fe 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -106,6 +106,7 @@ typedef struct VmdkExtent { + uint32_t l2_cache_counts[L2_CACHE_SIZE]; + + int64_t cluster_sectors; ++ char *type; + } VmdkExtent; + + typedef struct BDRVVmdkState { +@@ -113,11 +114,13 @@ typedef struct BDRVVmdkState { + uint64_t desc_offset; + bool cid_updated; + bool cid_checked; ++ uint32_t cid; + uint32_t parent_cid; + int num_extents; + /* Extent array with num_extents entries, ascend ordered by address */ + VmdkExtent *extents; + Error *migration_blocker; ++ char *create_type; + } BDRVVmdkState; + + typedef struct VmdkMetaData { +@@ -214,6 +217,7 @@ static void vmdk_free_extents(BlockDriverState *bs) + g_free(e->l1_table); + g_free(e->l2_cache); + g_free(e->l1_backup_table); ++ g_free(e->type); + if (e->file != bs->file) { + bdrv_delete(e->file); + } +@@ -534,6 +538,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + uint32_t l1_size, l1_entry_sectors; + VMDK4Header header; + VmdkExtent *extent; ++ BDRVVmdkState *s = bs->opaque; + int64_t l1_backup_offset = 0; + + ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); +@@ -549,6 +554,10 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + } + } + ++ if (!s->create_type) { ++ s->create_type = g_strdup("monolithicSparse"); ++ } ++ + if (le64_to_cpu(header.gd_offset) == VMDK4_GD_AT_END) { + /* + * The footer takes precedence over the header, so read it in. The +@@ -709,6 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + int64_t flat_offset; + char extent_path[PATH_MAX]; + BlockDriverState *extent_file; ++ BDRVVmdkState *s = bs->opaque; ++ VmdkExtent *extent; + + while (*p) { + /* parse extent line: +@@ -749,7 +760,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + /* save to extents array */ + if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) { + /* FLAT extent */ +- VmdkExtent *extent; + + ret = vmdk_add_extent(bs, extent_file, true, sectors, + 0, 0, 0, 0, 0, &extent, errp); +@@ -764,10 +774,12 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + bdrv_delete(extent_file); + return ret; + } ++ extent = &s->extents[s->num_extents - 1]; + } else { + error_setg(errp, "Unsupported extent type '%s'", type); + return -ENOTSUP; + } ++ extent->type = g_strdup(type); + next_line: + /* move to next line */ + while (*p && *p != '\n') { +@@ -812,6 +824,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + ret = -ENOTSUP; + goto exit; + } ++ s->create_type = g_strdup(ct); + s->desc_offset = 0; + ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp); + exit: +@@ -838,6 +851,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + if (ret) { + goto fail; + } ++ s->cid = vmdk_read_cid(bs, 0); + s->parent_cid = vmdk_read_cid(bs, 1); + qemu_co_mutex_init(&s->lock); + +@@ -850,6 +864,8 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + return 0; + + fail: ++ g_free(s->create_type); ++ s->create_type = NULL; + vmdk_free_extents(bs); + return ret; + } +@@ -1761,6 +1777,7 @@ static void vmdk_close(BlockDriverState *bs) + BDRVVmdkState *s = bs->opaque; + + vmdk_free_extents(bs); ++ g_free(s->create_type); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); +@@ -1822,6 +1839,54 @@ static int vmdk_has_zero_init(BlockDriverState *bs) + return 1; + } + ++static ImageInfo *vmdk_get_extent_info(VmdkExtent *extent) ++{ ++ ImageInfo *info = g_new0(ImageInfo, 1); ++ ++ *info = (ImageInfo){ ++ .filename = g_strdup(extent->file->filename), ++ .format = g_strdup(extent->type), ++ .virtual_size = extent->sectors * BDRV_SECTOR_SIZE, ++ .compressed = extent->compressed, ++ .has_compressed = extent->compressed, ++ .cluster_size = extent->cluster_sectors * BDRV_SECTOR_SIZE, ++ .has_cluster_size = !extent->flat, ++ }; ++ ++ return info; ++} ++ ++static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs) ++{ ++ int i; ++ BDRVVmdkState *s = bs->opaque; ++ ImageInfoSpecific *spec_info = g_new0(ImageInfoSpecific, 1); ++ ImageInfoList **next; ++ ++ *spec_info = (ImageInfoSpecific){ ++ .kind = IMAGE_INFO_SPECIFIC_KIND_VMDK, ++ { ++ .vmdk = g_new0(ImageInfoSpecificVmdk, 1), ++ }, ++ }; ++ ++ *spec_info->vmdk = (ImageInfoSpecificVmdk) { ++ .create_type = g_strdup(s->create_type), ++ .cid = s->cid, ++ .parent_cid = s->parent_cid, ++ }; ++ ++ next = &spec_info->vmdk->extents; ++ for (i = 0; i < s->num_extents; i++) { ++ *next = g_new0(ImageInfoList, 1); ++ (*next)->value = vmdk_get_extent_info(&s->extents[i]); ++ (*next)->next = NULL; ++ next = &(*next)->next; ++ } ++ ++ return spec_info; ++} ++ + static QEMUOptionParameter vmdk_create_options[] = { + { + .name = BLOCK_OPT_SIZE, +@@ -1874,6 +1939,7 @@ static BlockDriver bdrv_vmdk = { + .bdrv_co_get_block_status = vmdk_co_get_block_status, + .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, + .bdrv_has_zero_init = vmdk_has_zero_init, ++ .bdrv_get_specific_info = vmdk_get_specific_info, + + .create_options = vmdk_create_options, + }; +diff --git a/qapi-schema.json b/qapi-schema.json +index 99b05b7..64696a9 100644 +--- a/qapi-schema.json ++++ b/qapi-schema.json +@@ -225,6 +225,27 @@ + } } + + ## ++# @ImageInfoSpecificVmdk: ++# ++# @create_type: The create type of VMDK image ++# ++# @cid: Content id of image ++# ++# @parent-cid: Parent VMDK image's cid ++# ++# @extents: List of extent files ++# ++# Since: 1.7 ++## ++{ 'type': 'ImageInfoSpecificVmdk', ++ 'data': { ++ 'create-type': 'str', ++ 'cid': 'int', ++ 'parent-cid': 'int', ++ 'extents': ['ImageInfo'] ++ } } ++ ++## + # @ImageInfoSpecific: + # + # A discriminated record of image format specific information structures. +@@ -234,7 +255,8 @@ + + { 'union': 'ImageInfoSpecific', + 'data': { +- 'qcow2': 'ImageInfoSpecificQCow2' ++ 'qcow2': 'ImageInfoSpecificQCow2', ++ 'vmdk': 'ImageInfoSpecificVmdk' + } } + + ## +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index 26d4538..36103e1 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -69,7 +69,7 @@ poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00" + echo "=== Testing monolithicFlat creation and opening ===" + echo + IMGOPTS="subformat=monolithicFlat" _make_test_img 2G +-$QEMU_IMG info $TEST_IMG | _filter_testdir ++_img_info + + echo + echo "=== Testing monolithicFlat with zeroed_grain ===" +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 2b29ca9..5829794 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -18,10 +18,9 @@ no file open, try 'help open' + === Testing monolithicFlat creation and opening === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 +-image: TEST_DIR/t.vmdk +-file format: vmdk ++image: TEST_DIR/t.IMGFMT ++file format: IMGFMT + virtual size: 2.0G (2147483648 bytes) +-disk size: 4.0K + + === Testing monolithicFlat with zeroed_grain === + qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Make-VMDK3Header-and-VmdkGrainMarker-QEMU_PACKE.patch b/SOURCES/kvm-vmdk-Make-VMDK3Header-and-VmdkGrainMarker-QEMU_PACKE.patch new file mode 100644 index 0000000..b540436 --- /dev/null +++ b/SOURCES/kvm-vmdk-Make-VMDK3Header-and-VmdkGrainMarker-QEMU_PACKE.patch @@ -0,0 +1,50 @@ +From 48eeebecb8133d687cd86f33e1b9cee71baa2d35 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:47 +0800 +Subject: [PATCH 01/13] vmdk: Make VMDK3Header and VmdkGrainMarker QEMU_PACKED + +Message-id: <1377573001-27070-2-git-send-email-famz@redhat.com> +Patchwork-id: 53781 +O-Subject: [RHEL-7 qemu-kvm PATCH 01/13] vmdk: Make VMDK3Header and + VmdkGrainMarker QEMU_PACKED +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +It's best to make it consistent that all on disk structures are +QEMU_PACKED. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 5d8caa543c9714bee36b04899797a3721dff4090) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index f0c1f93..e85f4ea 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -62,7 +62,7 @@ typedef struct { + uint32_t cylinders; + uint32_t heads; + uint32_t sectors_per_track; +-} VMDK3Header; ++} QEMU_PACKED VMDK3Header; + + typedef struct { + uint32_t version; +@@ -131,7 +131,7 @@ typedef struct VmdkGrainMarker { + uint64_t lba; + uint32_t size; + uint8_t data[0]; +-} VmdkGrainMarker; ++} QEMU_PACKED VmdkGrainMarker; + + enum { + MARKER_END_OF_STREAM = 0, +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Move-l1_size-check-into-vmdk_add_extent.patch b/SOURCES/kvm-vmdk-Move-l1_size-check-into-vmdk_add_extent.patch new file mode 100644 index 0000000..d1187b0 --- /dev/null +++ b/SOURCES/kvm-vmdk-Move-l1_size-check-into-vmdk_add_extent.patch @@ -0,0 +1,62 @@ +From 71930418e15b0acb825fbd02dc4f954ccdea6ece Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 19 Aug 2013 18:54:25 +0800 +Subject: [PATCH 10/13] vmdk: Move l1_size check into vmdk_add_extent() + +Message-id: <1377573001-27070-11-git-send-email-famz@redhat.com> +Patchwork-id: 53790 +O-Subject: [RHEL-7 qemu-kvm PATCH 10/13] vmdk: Move l1_size check into + vmdk_add_extent() +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +This header check is common to VMDK3 and VMDK4, so move it into +vmdk_add_extent(). + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit b0651b8c246d0d9e6ad0831b3e34fd756016ad7e) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 73d9907..4388038 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -401,6 +401,14 @@ static int vmdk_add_extent(BlockDriverState *bs, + error_report("invalid granularity, image may be corrupt"); + return -EINVAL; + } ++ if (l1_size > 512 * 1024 * 1024) { ++ /* Although with big capacity and small l1_entry_sectors, we can get a ++ * big l1_size, we don't want unbounded value to allocate the table. ++ * Limit it to 512M, which is 16PB for default cluster and L2 table ++ * size */ ++ error_report("L1 size too big"); ++ return -EFBIG; ++ } + + s->extents = g_realloc(s->extents, + (s->num_extents + 1) * sizeof(VmdkExtent)); +@@ -598,14 +606,6 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + } + l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) + / l1_entry_sectors; +- if (l1_size > 512 * 1024 * 1024) { +- /* although with big capacity and small l1_entry_sectors, we can get a +- * big l1_size, we don't want unbounded value to allocate the table. +- * Limit it to 512M, which is 16PB for default cluster and L2 table +- * size */ +- error_report("L1 size too big"); +- return -EFBIG; +- } + if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) { + l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-Only-read-cid-from-image-file-when-opening.patch b/SOURCES/kvm-vmdk-Only-read-cid-from-image-file-when-opening.patch new file mode 100644 index 0000000..7f0fb76 --- /dev/null +++ b/SOURCES/kvm-vmdk-Only-read-cid-from-image-file-when-opening.patch @@ -0,0 +1,84 @@ +From 5bd906f28072f5d071705801cc1dd2e9084057bc Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:43 +0100 +Subject: [PATCH 86/87] vmdk: Only read cid from image file when opening + +RH-Author: Max Reitz +Message-id: <1383756824-6921-21-git-send-email-mreitz@redhat.com> +Patchwork-id: 55575 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 20/21] vmdk: Only read cid from image file when opening +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Previously cid of parent is parsed from image file for every IO request. +We already have L1/L2 cache and don't have assumption that parent image +can be updated behind us, so remove this to get more efficiency. + +The parent CID is checked only for once after opening. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit c338b6ad609699cf352c8dd6338360b7e3895ad0) + +Signed-off-by: Max Reitz +--- + block/vmdk.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 8 +++----- + 1 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index ccbb0c9..8bef9f2 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -112,6 +112,7 @@ typedef struct BDRVVmdkState { + CoMutex lock; + uint64_t desc_offset; + bool cid_updated; ++ bool cid_checked; + uint32_t parent_cid; + int num_extents; + /* Extent array with num_extents entries, ascend ordered by address */ +@@ -197,8 +198,6 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) + } + } + +-#define CHECK_CID 1 +- + #define SECTOR_SIZE 512 + #define DESC_SIZE (20 * SECTOR_SIZE) /* 20 sectors of 512 bytes each */ + #define BUF_SIZE 4096 +@@ -301,19 +300,18 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) + + static int vmdk_is_cid_valid(BlockDriverState *bs) + { +-#ifdef CHECK_CID + BDRVVmdkState *s = bs->opaque; + BlockDriverState *p_bs = bs->backing_hd; + uint32_t cur_pcid; + +- if (p_bs) { ++ if (!s->cid_checked && p_bs) { + cur_pcid = vmdk_read_cid(p_bs, 0); + if (s->parent_cid != cur_pcid) { + /* CID not valid */ + return 0; + } + } +-#endif ++ s->cid_checked = true; + /* CID valid */ + return 1; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-check-granularity-field-in-opening.patch b/SOURCES/kvm-vmdk-check-granularity-field-in-opening.patch new file mode 100644 index 0000000..8193ece --- /dev/null +++ b/SOURCES/kvm-vmdk-check-granularity-field-in-opening.patch @@ -0,0 +1,157 @@ +From c85b3af7587973944c28b859dfefa91c21852971 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:51 +0800 +Subject: [PATCH 05/13] vmdk: check granularity field in opening + +Message-id: <1377573001-27070-6-git-send-email-famz@redhat.com> +Patchwork-id: 53785 +O-Subject: [RHEL-7 qemu-kvm PATCH 05/13] vmdk: check granularity field in opening +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +Granularity is used to calculate the cluster size and allocate r/w +buffer. Check the value from image before using it, so we don't abort() +for unbounded memory allocation. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 8aa1331c09a9b899f48d97f097bb49b7d458be1c) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 40 +++++++++++++++++++++++++++++++--------- + tests/qemu-iotests/059 | 8 +++++++- + tests/qemu-iotests/059.out | 6 ++++++ + 3 files changed, 44 insertions(+), 10 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 78ea480..8f59697 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -385,15 +385,22 @@ static int vmdk_parent_open(BlockDriverState *bs) + + /* Create and append extent to the extent array. Return the added VmdkExtent + * address. return NULL if allocation failed. */ +-static VmdkExtent *vmdk_add_extent(BlockDriverState *bs, ++static int vmdk_add_extent(BlockDriverState *bs, + BlockDriverState *file, bool flat, int64_t sectors, + int64_t l1_offset, int64_t l1_backup_offset, + uint32_t l1_size, +- int l2_size, unsigned int cluster_sectors) ++ int l2_size, uint64_t cluster_sectors, ++ VmdkExtent **new_extent) + { + VmdkExtent *extent; + BDRVVmdkState *s = bs->opaque; + ++ if (cluster_sectors > 0x200000) { ++ /* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */ ++ error_report("invalid granularity, image may be corrupt"); ++ return -EINVAL; ++ } ++ + s->extents = g_realloc(s->extents, + (s->num_extents + 1) * sizeof(VmdkExtent)); + extent = &s->extents[s->num_extents]; +@@ -416,7 +423,10 @@ static VmdkExtent *vmdk_add_extent(BlockDriverState *bs, + extent->end_sector = extent->sectors; + } + bs->total_sectors = extent->end_sector; +- return extent; ++ if (new_extent) { ++ *new_extent = extent; ++ } ++ return 0; + } + + static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) +@@ -475,12 +485,17 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, + if (ret < 0) { + return ret; + } +- extent = vmdk_add_extent(bs, ++ ++ ret = vmdk_add_extent(bs, + bs->file, false, + le32_to_cpu(header.disk_sectors), + le32_to_cpu(header.l1dir_offset) << 9, + 0, 1 << 6, 1 << 9, +- le32_to_cpu(header.granularity)); ++ le32_to_cpu(header.granularity), ++ &extent); ++ if (ret < 0) { ++ return ret; ++ } + ret = vmdk_init_tables(bs, extent); + if (ret) { + /* free extent allocated by vmdk_add_extent */ +@@ -580,13 +595,17 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) { + l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9; + } +- extent = vmdk_add_extent(bs, file, false, ++ ret = vmdk_add_extent(bs, file, false, + le64_to_cpu(header.capacity), + le64_to_cpu(header.gd_offset) << 9, + l1_backup_offset, + l1_size, + le32_to_cpu(header.num_gtes_per_gte), +- le64_to_cpu(header.granularity)); ++ le64_to_cpu(header.granularity), ++ &extent); ++ if (ret < 0) { ++ return ret; ++ } + extent->compressed = + le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE; + extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER; +@@ -702,8 +721,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + /* FLAT extent */ + VmdkExtent *extent; + +- extent = vmdk_add_extent(bs, extent_file, true, sectors, +- 0, 0, 0, 0, sectors); ++ ret = vmdk_add_extent(bs, extent_file, true, sectors, ++ 0, 0, 0, 0, sectors, &extent); ++ if (ret < 0) { ++ return ret; ++ } + extent->flat_start_offset = flat_offset << 9; + } else if (!strcmp(type, "SPARSE")) { + /* SPARSE extent */ +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index 9dc7f64..9545e82 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -43,7 +43,13 @@ _supported_fmt vmdk + _supported_proto generic + _supported_os Linux + +-granularity_offset=16 ++granularity_offset=20 ++ ++echo "=== Testing invalid granularity ===" ++echo ++_make_test_img 64M ++poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff" ++{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + + # success, all done + echo "*** done" +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 4ca7f29..380ca3d 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -1,2 +1,8 @@ + QA output created by 059 ++=== Testing invalid granularity === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++invalid granularity, image may be corrupt ++qemu-io: can't open device TEST_DIR/t.vmdk ++no file open, try 'help open' + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-check-l1-size-before-opening-image.patch b/SOURCES/kvm-vmdk-check-l1-size-before-opening-image.patch new file mode 100644 index 0000000..cdbff84 --- /dev/null +++ b/SOURCES/kvm-vmdk-check-l1-size-before-opening-image.patch @@ -0,0 +1,90 @@ +From e00b646f642f10be545014c866a71b268d90e67a Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:53 +0800 +Subject: [PATCH 07/13] vmdk: check l1 size before opening image + +Message-id: <1377573001-27070-8-git-send-email-famz@redhat.com> +Patchwork-id: 53786 +O-Subject: [RHEL-7 qemu-kvm PATCH 07/13] vmdk: check l1 size before opening image +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +L1 table size is calculated from capacity, granularity and l2 table +size. If capacity is too big or later two are too small, the L1 table +will be too big to allocate in memory. Limit it to a reasonable range. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 2c43e43c8cec130fff95ef720a860e91efb36685) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 8 ++++++++ + tests/qemu-iotests/059 | 8 ++++++++ + tests/qemu-iotests/059.out | 6 ++++++ + 3 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index b2a3fe2..58163ef 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -597,6 +597,14 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + } + l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) + / l1_entry_sectors; ++ if (l1_size > 512 * 1024 * 1024) { ++ /* although with big capacity and small l1_entry_sectors, we can get a ++ * big l1_size, we don't want unbounded value to allocate the table. ++ * Limit it to 512M, which is 16PB for default cluster and L2 table ++ * size */ ++ error_report("L1 size too big"); ++ return -EFBIG; ++ } + if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) { + l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9; + } +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index 301eaca..b03429d 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -43,6 +43,7 @@ _supported_fmt vmdk + _supported_proto generic + _supported_os Linux + ++capacity_offset=16 + granularity_offset=20 + grain_table_size_offset=44 + +@@ -58,6 +59,13 @@ _make_test_img 64M + poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff" + { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + ++echo "=== Testing too big L1 table size ===" ++echo ++_make_test_img 64M ++poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff" ++poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00" ++{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 583955f..9e715e5 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -11,4 +11,10 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + L2 table size too big + qemu-io: can't open device TEST_DIR/t.vmdk + no file open, try 'help open' ++=== Testing too big L1 table size === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++L1 size too big ++qemu-io: can't open device TEST_DIR/t.vmdk ++no file open, try 'help open' + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-check-l2-table-size-when-opening.patch b/SOURCES/kvm-vmdk-check-l2-table-size-when-opening.patch new file mode 100644 index 0000000..62a4f8b --- /dev/null +++ b/SOURCES/kvm-vmdk-check-l2-table-size-when-opening.patch @@ -0,0 +1,85 @@ +From 6442a27eaebb5a42ef26a73f0efcf0166f70b235 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:52 +0800 +Subject: [PATCH 06/13] vmdk: check l2 table size when opening + +Message-id: <1377573001-27070-7-git-send-email-famz@redhat.com> +Patchwork-id: 53787 +O-Subject: [RHEL-7 qemu-kvm PATCH 06/13] vmdk: check l2 table size when opening +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +header.num_gtes_per_gte determines size for L2 table. Check for too big +value before using it. Limit to 512M entries (2GB per one L2 table). + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit f8ce04036e333aae480b1d06d969f6436652633d) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 5 +++++ + tests/qemu-iotests/059 | 7 +++++++ + tests/qemu-iotests/059.out | 6 ++++++ + 3 files changed, 18 insertions(+), 0 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 8f59697..b2a3fe2 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -585,6 +585,11 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + return -ENOTSUP; + } + ++ if (le32_to_cpu(header.num_gtes_per_gte) > 512) { ++ error_report("L2 table size too big"); ++ return -EINVAL; ++ } ++ + l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) + * le64_to_cpu(header.granularity); + if (l1_entry_sectors == 0) { +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index 9545e82..301eaca 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -44,6 +44,7 @@ _supported_proto generic + _supported_os Linux + + granularity_offset=20 ++grain_table_size_offset=44 + + echo "=== Testing invalid granularity ===" + echo +@@ -51,6 +52,12 @@ _make_test_img 64M + poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff" + { $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir + ++echo "=== Testing too big L2 table size ===" ++echo ++_make_test_img 64M ++poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff" ++{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 380ca3d..583955f 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -5,4 +5,10 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + invalid granularity, image may be corrupt + qemu-io: can't open device TEST_DIR/t.vmdk + no file open, try 'help open' ++=== Testing too big L2 table size === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 ++L2 table size too big ++qemu-io: can't open device TEST_DIR/t.vmdk ++no file open, try 'help open' + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-convert-error-code-to-use-errp.patch b/SOURCES/kvm-vmdk-convert-error-code-to-use-errp.patch new file mode 100644 index 0000000..3100e6f --- /dev/null +++ b/SOURCES/kvm-vmdk-convert-error-code-to-use-errp.patch @@ -0,0 +1,455 @@ +From 57c326f0b2220c9bbe1968f3cc251ae2f99db8ae Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:40 +0100 +Subject: [PATCH 83/87] vmdk: convert error code to use errp + +RH-Author: Max Reitz +Message-id: <1383756824-6921-18-git-send-email-mreitz@redhat.com> +Patchwork-id: 55572 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 17/21] vmdk: convert error code to use errp +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +Convert "fprintf(stderr,..." and standardize error messages: + +Remove a few local_error's and use errp. + +Remove "VMDK:" or "Vmdk:" prefixes in error message and fix to upper +case. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 4823970bcb882cd5b7e9c9a21fa6573190035050) + +Signed-off-by: Max Reitz + +Conflicts: + block/vmdk.c + +Conflicts because the series "Implement reference count for +BlockDriverState" has not yet been backported which "replaces" +bdrv_delete by bdrv_unref. +--- + block/vmdk.c | 116 ++++++++++++++++++++++++--------------------- + tests/qemu-iotests/059.out | 6 +-- + 2 files changed, 63 insertions(+), 59 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 116 +++++++++++++++++++++++--------------------- + tests/qemu-iotests/059.out | 6 +-- + 2 files changed, 63 insertions(+), 59 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index bd1dd62..96f9415 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -331,8 +331,7 @@ static int vmdk_reopen_prepare(BDRVReopenState *state, + assert(state->bs != NULL); + + if (queue == NULL) { +- error_set(errp, ERROR_CLASS_GENERIC_ERROR, +- "No reopen queue for VMDK extents"); ++ error_setg(errp, "No reopen queue for VMDK extents"); + goto exit; + } + +@@ -391,22 +390,23 @@ static int vmdk_add_extent(BlockDriverState *bs, + int64_t l1_offset, int64_t l1_backup_offset, + uint32_t l1_size, + int l2_size, uint64_t cluster_sectors, +- VmdkExtent **new_extent) ++ VmdkExtent **new_extent, ++ Error **errp) + { + VmdkExtent *extent; + BDRVVmdkState *s = bs->opaque; + + if (cluster_sectors > 0x200000) { + /* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */ +- error_report("invalid granularity, image may be corrupt"); +- return -EINVAL; ++ error_setg(errp, "Invalid granularity, image may be corrupt"); ++ return -EFBIG; + } + if (l1_size > 512 * 1024 * 1024) { + /* Although with big capacity and small l1_entry_sectors, we can get a + * big l1_size, we don't want unbounded value to allocate the table. + * Limit it to 512M, which is 16PB for default cluster and L2 table + * size */ +- error_report("L1 size too big"); ++ error_setg(errp, "L1 size too big"); + return -EFBIG; + } + +@@ -438,7 +438,8 @@ static int vmdk_add_extent(BlockDriverState *bs, + return 0; + } + +-static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) ++static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent, ++ Error **errp) + { + int ret; + int l1_size, i; +@@ -447,10 +448,13 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) + l1_size = extent->l1_size * sizeof(uint32_t); + extent->l1_table = g_malloc(l1_size); + ret = bdrv_pread(extent->file, +- extent->l1_table_offset, +- extent->l1_table, +- l1_size); ++ extent->l1_table_offset, ++ extent->l1_table, ++ l1_size); + if (ret < 0) { ++ error_setg_errno(errp, -ret, ++ "Could not read l1 table from extent '%s'", ++ extent->file->filename); + goto fail_l1; + } + for (i = 0; i < extent->l1_size; i++) { +@@ -460,10 +464,13 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) + if (extent->l1_backup_table_offset) { + extent->l1_backup_table = g_malloc(l1_size); + ret = bdrv_pread(extent->file, +- extent->l1_backup_table_offset, +- extent->l1_backup_table, +- l1_size); ++ extent->l1_backup_table_offset, ++ extent->l1_backup_table, ++ l1_size); + if (ret < 0) { ++ error_setg_errno(errp, -ret, ++ "Could not read l1 backup table from extent '%s'", ++ extent->file->filename); + goto fail_l1b; + } + for (i = 0; i < extent->l1_size; i++) { +@@ -483,7 +490,7 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) + + static int vmdk_open_vmfs_sparse(BlockDriverState *bs, + BlockDriverState *file, +- int flags) ++ int flags, Error **errp) + { + int ret; + uint32_t magic; +@@ -492,6 +499,9 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs, + + ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); + if (ret < 0) { ++ error_setg_errno(errp, -ret, ++ "Could not read header from file '%s'", ++ file->filename); + return ret; + } + ret = vmdk_add_extent(bs, file, false, +@@ -501,11 +511,12 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs, + le32_to_cpu(header.l1dir_size), + 4096, + le32_to_cpu(header.granularity), +- &extent); ++ &extent, ++ errp); + if (ret < 0) { + return ret; + } +- ret = vmdk_init_tables(bs, extent); ++ ret = vmdk_init_tables(bs, extent, errp); + if (ret) { + /* free extent allocated by vmdk_add_extent */ + vmdk_free_last_extent(bs); +@@ -514,11 +525,11 @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs, + } + + static int vmdk_open_desc_file(BlockDriverState *bs, int flags, +- uint64_t desc_offset); ++ uint64_t desc_offset, Error **errp); + + static int vmdk_open_vmdk4(BlockDriverState *bs, + BlockDriverState *file, +- int flags) ++ int flags, Error **errp) + { + int ret; + uint32_t magic; +@@ -529,12 +540,14 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + + ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header)); + if (ret < 0) { +- return ret; ++ error_setg_errno(errp, -ret, ++ "Could not read header from file '%s'", ++ file->filename); + } + if (header.capacity == 0) { + uint64_t desc_offset = le64_to_cpu(header.desc_offset); + if (desc_offset) { +- return vmdk_open_desc_file(bs, flags, desc_offset << 9); ++ return vmdk_open_desc_file(bs, flags, desc_offset << 9, errp); + } + } + +@@ -616,7 +629,8 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + l1_size, + le32_to_cpu(header.num_gtes_per_gt), + le64_to_cpu(header.granularity), +- &extent); ++ &extent, ++ errp); + if (ret < 0) { + return ret; + } +@@ -625,7 +639,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER; + extent->version = le32_to_cpu(header.version); + extent->has_zero_grain = le32_to_cpu(header.flags) & VMDK4_FLAG_ZERO_GRAIN; +- ret = vmdk_init_tables(bs, extent); ++ ret = vmdk_init_tables(bs, extent, errp); + if (ret) { + /* free extent allocated by vmdk_add_extent */ + vmdk_free_last_extent(bs); +@@ -663,7 +677,7 @@ static int vmdk_parse_description(const char *desc, const char *opt_name, + /* Open an extent file and append to bs array */ + static int vmdk_open_sparse(BlockDriverState *bs, + BlockDriverState *file, +- int flags) ++ int flags, Error **errp) + { + uint32_t magic; + +@@ -674,10 +688,10 @@ static int vmdk_open_sparse(BlockDriverState *bs, + magic = be32_to_cpu(magic); + switch (magic) { + case VMDK3_MAGIC: +- return vmdk_open_vmfs_sparse(bs, file, flags); ++ return vmdk_open_vmfs_sparse(bs, file, flags, errp); + break; + case VMDK4_MAGIC: +- return vmdk_open_vmdk4(bs, file, flags); ++ return vmdk_open_vmdk4(bs, file, flags, errp); + break; + default: + return -EMEDIUMTYPE; +@@ -686,7 +700,7 @@ static int vmdk_open_sparse(BlockDriverState *bs, + } + + static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, +- const char *desc_file_path) ++ const char *desc_file_path, Error **errp) + { + int ret; + char access[11]; +@@ -697,7 +711,6 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + int64_t flat_offset; + char extent_path[PATH_MAX]; + BlockDriverState *extent_file; +- Error *local_err = NULL; + + while (*p) { + /* parse extent line: +@@ -712,9 +725,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + goto next_line; + } else if (!strcmp(type, "FLAT")) { + if (ret != 5 || flat_offset < 0) { ++ error_setg(errp, "Invalid extent lines: \n%s", p); + return -EINVAL; + } + } else if (ret != 4) { ++ error_setg(errp, "Invalid extent lines: \n%s", p); + return -EINVAL; + } + +@@ -728,10 +743,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + path_combine(extent_path, sizeof(extent_path), + desc_file_path, fname); + ret = bdrv_file_open(&extent_file, extent_path, NULL, bs->open_flags, +- &local_err); ++ errp); + if (ret) { +- qerror_report_err(local_err); +- error_free(local_err); + return ret; + } + +@@ -741,21 +754,20 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + VmdkExtent *extent; + + ret = vmdk_add_extent(bs, extent_file, true, sectors, +- 0, 0, 0, 0, 0, &extent); ++ 0, 0, 0, 0, 0, &extent, errp); + if (ret < 0) { + return ret; + } + extent->flat_start_offset = flat_offset << 9; + } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) { + /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/ +- ret = vmdk_open_sparse(bs, extent_file, bs->open_flags); ++ ret = vmdk_open_sparse(bs, extent_file, bs->open_flags, errp); + if (ret) { + bdrv_delete(extent_file); + return ret; + } + } else { +- fprintf(stderr, +- "VMDK: Not supported extent type \"%s\""".\n", type); ++ error_setg(errp, "Unsupported extent type '%s'", type); + return -ENOTSUP; + } + next_line: +@@ -769,7 +781,7 @@ next_line: + } + + static int vmdk_open_desc_file(BlockDriverState *bs, int flags, +- uint64_t desc_offset) ++ uint64_t desc_offset, Error **errp) + { + int ret; + char *buf = NULL; +@@ -798,13 +810,12 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + strcmp(ct, "vmfsSparse") && + strcmp(ct, "twoGbMaxExtentSparse") && + strcmp(ct, "twoGbMaxExtentFlat")) { +- fprintf(stderr, +- "VMDK: Not supported image type \"%s\""".\n", ct); ++ error_setg(errp, "Unsupported image type '%s'", ct); + ret = -ENOTSUP; + goto exit; + } + s->desc_offset = 0; +- ret = vmdk_parse_extents(buf, bs, bs->file->filename); ++ ret = vmdk_parse_extents(buf, bs, bs->file->filename, errp); + exit: + g_free(buf); + return ret; +@@ -816,10 +827,10 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags, + int ret; + BDRVVmdkState *s = bs->opaque; + +- if (vmdk_open_sparse(bs, bs->file, flags) == 0) { ++ if (vmdk_open_sparse(bs, bs->file, flags, errp) == 0) { + s->desc_offset = 0x200; + } else { +- ret = vmdk_open_desc_file(bs, flags, 0); ++ ret = vmdk_open_desc_file(bs, flags, 0, errp); + if (ret) { + goto fail; + } +@@ -1286,8 +1297,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, + VmdkMetaData m_data; + + if (sector_num > bs->total_sectors) { +- fprintf(stderr, +- "(VMDK) Wrong offset: sector_num=0x%" PRIx64 ++ error_report("Wrong offset: sector_num=0x%" PRIx64 + " total_sectors=0x%" PRIx64 "\n", + sector_num, bs->total_sectors); + return -EIO; +@@ -1307,9 +1317,8 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num, + if (extent->compressed) { + if (ret == VMDK_OK) { + /* Refuse write to allocated cluster for streamOptimized */ +- fprintf(stderr, +- "VMDK: can't write to allocated cluster" +- " for streamOptimized\n"); ++ error_report("Could not write to allocated cluster" ++ " for streamOptimized"); + return -EIO; + } else { + /* allocate */ +@@ -1517,12 +1526,12 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, + } + + static int filename_decompose(const char *filename, char *path, char *prefix, +- char *postfix, size_t buf_len) ++ char *postfix, size_t buf_len, Error **errp) + { + const char *p, *q; + + if (filename == NULL || !strlen(filename)) { +- fprintf(stderr, "Vmdk: no filename provided.\n"); ++ error_setg(errp, "No filename provided"); + return VMDK_ERROR; + } + p = strrchr(filename, '/'); +@@ -1595,9 +1604,8 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + "ddb.geometry.heads = \"%d\"\n" + "ddb.geometry.sectors = \"63\"\n" + "ddb.adapterType = \"%s\"\n"; +- Error *local_err = NULL; + +- if (filename_decompose(filename, path, prefix, postfix, PATH_MAX)) { ++ if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp)) { + return -EINVAL; + } + /* Read out options */ +@@ -1623,7 +1631,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + strcmp(adapter_type, "buslogic") && + strcmp(adapter_type, "lsilogic") && + strcmp(adapter_type, "legacyESX")) { +- fprintf(stderr, "VMDK: Unknown adapter type: '%s'.\n", adapter_type); ++ error_setg(errp, "Unknown adapter type: '%s'", adapter_type); + return -EINVAL; + } + if (strcmp(adapter_type, "ide") != 0) { +@@ -1639,7 +1647,7 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + strcmp(fmt, "twoGbMaxExtentSparse") && + strcmp(fmt, "twoGbMaxExtentFlat") && + strcmp(fmt, "streamOptimized")) { +- fprintf(stderr, "VMDK: Unknown subformat: %s\n", fmt); ++ error_setg(errp, "Unknown subformat: '%s'", fmt); + return -EINVAL; + } + split = !(strcmp(fmt, "twoGbMaxExtentFlat") && +@@ -1653,15 +1661,13 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + desc_extent_line = "RW %lld SPARSE \"%s\"\n"; + } + if (flat && backing_file) { +- /* not supporting backing file for flat image */ ++ error_setg(errp, "Flat image can't have backing file"); + return -ENOTSUP; + } + if (backing_file) { + BlockDriverState *bs = bdrv_new(""); +- ret = bdrv_open(bs, backing_file, NULL, 0, NULL, &local_err); ++ ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp); + if (ret != 0) { +- qerror_report_err(local_err); +- error_free(local_err); + bdrv_delete(bs); + return ret; + } +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index 9159dbe..dc4f024 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -2,8 +2,7 @@ QA output created by 059 + === Testing invalid granularity === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +-invalid granularity, image may be corrupt +-qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type ++qemu-io: can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt + no file open, try 'help open' + === Testing too big L2 table size === + +@@ -14,8 +13,7 @@ no file open, try 'help open' + === Testing too big L1 table size === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +-L1 size too big +-qemu-io: can't open device TEST_DIR/t.vmdk: Could not open 'TEST_DIR/t.vmdk': Wrong medium type ++qemu-io: can't open device TEST_DIR/t.vmdk: L1 size too big + no file open, try 'help open' + === Testing monolithicFlat creation and opening === + +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-fix-L1-and-L2-table-size-in-vmdk3-open.patch b/SOURCES/kvm-vmdk-fix-L1-and-L2-table-size-in-vmdk3-open.patch new file mode 100644 index 0000000..94709f5 --- /dev/null +++ b/SOURCES/kvm-vmdk-fix-L1-and-L2-table-size-in-vmdk3-open.patch @@ -0,0 +1,61 @@ +From abce415a153d6bdf7068e812e3847ba559d33081 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 19 Aug 2013 18:54:26 +0800 +Subject: [PATCH 11/13] vmdk: fix L1 and L2 table size in vmdk3 open + +Message-id: <1377573001-27070-12-git-send-email-famz@redhat.com> +Patchwork-id: 53791 +O-Subject: [RHEL-7 qemu-kvm PATCH 11/13] vmdk: fix L1 and L2 table size in vmdk3 + open +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +VMDK3 header has the field l1dir_size, but vmdk_open_vmdk3 hardcoded the +value. This patch honors the header field. + +And the L2 table size is 4096 according to VMDK spec[1], instead of +1 << 9 (512). + +[1]: +http://www.vmware.com/support/developer/vddk/vmdk_50_technote.pdf?src=vmdk + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit f6b61e54bdd5b9ef46837c15547e1819b3bb4f37) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 16 ++++++++-------- + 1 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 4388038..4997da4 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -494,14 +494,14 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, + if (ret < 0) { + return ret; + } +- +- ret = vmdk_add_extent(bs, +- bs->file, false, +- le32_to_cpu(header.disk_sectors), +- le32_to_cpu(header.l1dir_offset) << 9, +- 0, 1 << 6, 1 << 9, +- le32_to_cpu(header.granularity), +- &extent); ++ ret = vmdk_add_extent(bs, file, false, ++ le32_to_cpu(header.disk_sectors), ++ le32_to_cpu(header.l1dir_offset) << 9, ++ 0, ++ le32_to_cpu(header.l1dir_size), ++ 4096, ++ le32_to_cpu(header.granularity), ++ &extent); + if (ret < 0) { + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-fix-VMFS-extent-parsing.patch b/SOURCES/kvm-vmdk-fix-VMFS-extent-parsing.patch new file mode 100644 index 0000000..ca439fd --- /dev/null +++ b/SOURCES/kvm-vmdk-fix-VMFS-extent-parsing.patch @@ -0,0 +1,43 @@ +From dc64463e65223377bfb4a925f2f047b50090b32a Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 7 Nov 2013 16:07:08 +0100 +Subject: [PATCH 23/25] vmdk: fix VMFS extent parsing + +RH-Author: Fam Zheng +Message-id: <1383795369-10623-3-git-send-email-famz@redhat.com> +Patchwork-id: 55586 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/2] vmdk: fix VMFS extent parsing +Bugzilla: 995866 +RH-Acked-by: Amos Kong +RH-Acked-by: Max Reitz +RH-Acked-by: Kevin Wolf + +The VMFS extent line in description file doesn't have start offset as +FLAT lines does, and it should be defaulted to 0. The flat_offset +variable is initialized to -1, so we need to set it in this case. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit dbbcaa8d4358fdf3c42bf01e9e2d687300e84770) +Signed-off-by: Fam Zheng +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index f2237cf..026b440 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -737,6 +737,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + error_setg(errp, "Invalid extent lines: \n%s", p); + return -EINVAL; + } ++ } else if (!strcmp(type, "VMFS")) { ++ flat_offset = 0; + } else if (ret != 4) { + error_setg(errp, "Invalid extent lines: \n%s", p); + return -EINVAL; +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-fix-cluster-size-check-for-flat-extents.patch b/SOURCES/kvm-vmdk-fix-cluster-size-check-for-flat-extents.patch new file mode 100644 index 0000000..8e8a531 --- /dev/null +++ b/SOURCES/kvm-vmdk-fix-cluster-size-check-for-flat-extents.patch @@ -0,0 +1,80 @@ +From cbffbb8195ec5370cbb2baf53148806b5a1c3dc8 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Wed, 9 Oct 2013 09:50:22 +0200 +Subject: [PATCH 10/11] vmdk: fix cluster size check for flat extents + +RH-Author: Fam Zheng +Message-id: <1381312223-7074-3-git-send-email-famz@redhat.com> +Patchwork-id: 54794 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/3] vmdk: fix cluster size check for flat extents +Bugzilla: 1017049 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Miroslav Rezanina + +We use the extent size as cluster size for flat extents (where no L1/L2 +table is allocated so it's safe) reuse sector calculating code with +sparse extents. + +Don't pass in the cluster size for adding flat extent, just set it to +sectors later, then the cluster size checking will not fail. + +The cluster_sectors is changed to int64_t to allow big flat extent. + +Without this, flat extent opening is broken: + + # qemu-img create -f vmdk -o subformat=monolithicFlat /tmp/a.vmdk 100G + Formatting '/tmp/a.vmdk', fmt=vmdk size=107374182400 compat6=off subformat='monolithicFlat' zeroed_grain=off + # qemu-img info /tmp/a.vmdk + image: /tmp/a.vmdk + file format: raw + virtual size: 0 (0 bytes) + disk size: 4.0K + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 301c7d38a0c359b91526391d13617386f3d9bb29) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index b0b419b..66735ab 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -105,7 +105,7 @@ typedef struct VmdkExtent { + uint32_t l2_cache_offsets[L2_CACHE_SIZE]; + uint32_t l2_cache_counts[L2_CACHE_SIZE]; + +- unsigned int cluster_sectors; ++ int64_t cluster_sectors; + } VmdkExtent; + + typedef struct BDRVVmdkState { +@@ -424,7 +424,7 @@ static int vmdk_add_extent(BlockDriverState *bs, + extent->l1_size = l1_size; + extent->l1_entry_sectors = l2_size * cluster_sectors; + extent->l2_size = l2_size; +- extent->cluster_sectors = cluster_sectors; ++ extent->cluster_sectors = flat ? sectors : cluster_sectors; + + if (s->num_extents > 1) { + extent->end_sector = (*(extent - 1)).end_sector + extent->sectors; +@@ -737,7 +737,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + VmdkExtent *extent; + + ret = vmdk_add_extent(bs, extent_file, true, sectors, +- 0, 0, 0, 0, sectors, &extent); ++ 0, 0, 0, 0, 0, &extent); + if (ret < 0) { + return ret; + } +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-fix-comment-for-vmdk_co_write_zeroes.patch b/SOURCES/kvm-vmdk-fix-comment-for-vmdk_co_write_zeroes.patch new file mode 100644 index 0000000..8f994a0 --- /dev/null +++ b/SOURCES/kvm-vmdk-fix-comment-for-vmdk_co_write_zeroes.patch @@ -0,0 +1,63 @@ +From 7bae8147abc5661103da3316f09306939ec03708 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 5 Sep 2013 08:45:39 +0200 +Subject: [PATCH 11/29] vmdk: fix comment for vmdk_co_write_zeroes + +RH-Author: Fam Zheng +Message-id: <1378370739-22259-1-git-send-email-famz@redhat.com> +Patchwork-id: 54100 +O-Subject: [RHEL-7 qemu-kvm PATCH] vmdk: fix comment for vmdk_co_write_zeroes +Bugzilla: 995866 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Max Reitz + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=995866 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6246791 +Upstream: merged + +The comment was truncated. Add the missing parts, especially explain why +we need zero_dry_run. + +Signed-off-by: Fam Zheng +Signed-off-by: Michael Tokarev +(cherry picked from commit 8e50724313895a87057cc243ad805f2eb21feb9f) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index a28fb5e..f0c1f93 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1200,8 +1200,10 @@ static coroutine_fn int vmdk_co_read(BlockDriverState *bs, int64_t sector_num, + /** + * vmdk_write: + * @zeroed: buf is ignored (data is zero), use zeroed_grain GTE feature +- * if possible, otherwise return -ENOTSUP. +- * @zero_dry_run: used for zeroed == true only, don't update L2 table, just ++ * if possible, otherwise return -ENOTSUP. ++ * @zero_dry_run: used for zeroed == true only, don't update L2 table, just try ++ * with each cluster. By dry run we can find if the zero write ++ * is possible without modifying image data. + * + * Returns: error code with 0 for success. + */ +@@ -1328,6 +1330,8 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, + int ret; + BDRVVmdkState *s = bs->opaque; + qemu_co_mutex_lock(&s->lock); ++ /* write zeroes could fail if sectors not aligned to cluster, test it with ++ * dry_run == true before really updating image */ + ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true); + if (!ret) { + ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false); +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-refuse-enabling-zeroed-grain-with-flat-images.patch b/SOURCES/kvm-vmdk-refuse-enabling-zeroed-grain-with-flat-images.patch new file mode 100644 index 0000000..030d296 --- /dev/null +++ b/SOURCES/kvm-vmdk-refuse-enabling-zeroed-grain-with-flat-images.patch @@ -0,0 +1,84 @@ +From 0cc9ce211d3b571e35b5440fc12a77195b7ee804 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 6 Nov 2013 16:53:41 +0100 +Subject: [PATCH 84/87] vmdk: refuse enabling zeroed grain with flat images + +RH-Author: Max Reitz +Message-id: <1383756824-6921-19-git-send-email-mreitz@redhat.com> +Patchwork-id: 55573 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 18/21] vmdk: refuse enabling zeroed grain with flat images +Bugzilla: 980771 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Fam Zheng +RH-Acked-by: Jeffrey Cody + +From: Fam Zheng + +BZ: 980771 + +This is a header flag and we needs sparse for the header. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 52c8d629cac27ad16dd51507b4733d46fa4efc55) + +Signed-off-by: Max Reitz +--- + block/vmdk.c | 4 ++++ + tests/qemu-iotests/059 | 4 ++++ + tests/qemu-iotests/059.out | 4 ++++ + 3 files changed, 12 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + block/vmdk.c | 4 ++++ + tests/qemu-iotests/059 | 4 ++++ + tests/qemu-iotests/059.out | 4 ++++ + 3 files changed, 12 insertions(+), 0 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 96f9415..ccbb0c9 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -1664,6 +1664,10 @@ static int vmdk_create(const char *filename, QEMUOptionParameter *options, + error_setg(errp, "Flat image can't have backing file"); + return -ENOTSUP; + } ++ if (flat && zeroed_grain) { ++ error_setg(errp, "Flat image can't enable zeroed grain"); ++ return -ENOTSUP; ++ } + if (backing_file) { + BlockDriverState *bs = bdrv_new(""); + ret = bdrv_open(bs, backing_file, NULL, 0, NULL, errp); +diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 +index dd6addf..26d4538 100755 +--- a/tests/qemu-iotests/059 ++++ b/tests/qemu-iotests/059 +@@ -71,6 +71,10 @@ echo + IMGOPTS="subformat=monolithicFlat" _make_test_img 2G + $QEMU_IMG info $TEST_IMG | _filter_testdir + ++echo ++echo "=== Testing monolithicFlat with zeroed_grain ===" ++IMGOPTS="subformat=monolithicFlat,zeroed_grain=on" _make_test_img 2G ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index dc4f024..2b29ca9 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -22,4 +22,8 @@ image: TEST_DIR/t.vmdk + file format: vmdk + virtual size: 2.0G (2147483648 bytes) + disk size: 4.0K ++ ++=== Testing monolithicFlat with zeroed_grain === ++qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 + *** done +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-rename-num_gtes_per_gte-to-num_gtes_per_gt.patch b/SOURCES/kvm-vmdk-rename-num_gtes_per_gte-to-num_gtes_per_gt.patch new file mode 100644 index 0000000..68cd08f --- /dev/null +++ b/SOURCES/kvm-vmdk-rename-num_gtes_per_gte-to-num_gtes_per_gt.patch @@ -0,0 +1,91 @@ +From 92803fbc4c637faa21cc28e77ca400d9427f2554 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:55 +0800 +Subject: [PATCH 09/13] vmdk: rename num_gtes_per_gte to num_gtes_per_gt + +Message-id: <1377573001-27070-10-git-send-email-famz@redhat.com> +Patchwork-id: 53789 +O-Subject: [RHEL-7 qemu-kvm PATCH 09/13] vmdk: rename num_gtes_per_gte to + num_gtes_per_gt +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +num_gtes_per_gte is a historical typo, rename it to a more sensible +name. It means "number of GrainTableEntries per GrainTable". + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit ca8804ced9fdba7a1925ed81084dfb7a5b6ffa9f) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 17 +++++++++-------- + 1 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 1af6122..73d9907 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -71,7 +71,8 @@ typedef struct { + uint64_t granularity; + uint64_t desc_offset; + uint64_t desc_size; +- uint32_t num_gtes_per_gte; ++ /* Number of GrainTableEntries per GrainTable */ ++ uint32_t num_gtes_per_gt; + uint64_t rgd_offset; + uint64_t gd_offset; + uint64_t grain_offset; +@@ -585,12 +586,12 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + return -ENOTSUP; + } + +- if (le32_to_cpu(header.num_gtes_per_gte) > 512) { ++ if (le32_to_cpu(header.num_gtes_per_gt) > 512) { + error_report("L2 table size too big"); + return -EINVAL; + } + +- l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) ++ l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt) + * le64_to_cpu(header.granularity); + if (l1_entry_sectors == 0) { + return -EINVAL; +@@ -613,7 +614,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + le64_to_cpu(header.gd_offset) << 9, + l1_backup_offset, + l1_size, +- le32_to_cpu(header.num_gtes_per_gte), ++ le32_to_cpu(header.num_gtes_per_gt), + le64_to_cpu(header.granularity), + &extent); + if (ret < 0) { +@@ -1411,12 +1412,12 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, + header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0; + header.capacity = filesize / 512; + header.granularity = 128; +- header.num_gtes_per_gte = 512; ++ header.num_gtes_per_gt = 512; + + grains = (filesize / 512 + header.granularity - 1) / header.granularity; +- gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9; ++ gt_size = ((header.num_gtes_per_gt * sizeof(uint32_t)) + 511) >> 9; + gt_count = +- (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte; ++ (grains + header.num_gtes_per_gt - 1) / header.num_gtes_per_gt; + gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9; + + header.desc_offset = 1; +@@ -1432,7 +1433,7 @@ static int vmdk_create_extent(const char *filename, int64_t filesize, + header.flags = cpu_to_le32(header.flags); + header.capacity = cpu_to_le64(header.capacity); + header.granularity = cpu_to_le64(header.granularity); +- header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte); ++ header.num_gtes_per_gt = cpu_to_le32(header.num_gtes_per_gt); + header.desc_offset = cpu_to_le64(header.desc_offset); + header.desc_size = cpu_to_le64(header.desc_size); + header.rgd_offset = cpu_to_le64(header.rgd_offset); +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-support-vmfs-files.patch b/SOURCES/kvm-vmdk-support-vmfs-files.patch new file mode 100644 index 0000000..0b638c4 --- /dev/null +++ b/SOURCES/kvm-vmdk-support-vmfs-files.patch @@ -0,0 +1,60 @@ +From f9da89c13d9e9bde2d5da525ea6ad2ac92404ec4 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 19 Aug 2013 18:54:28 +0800 +Subject: [PATCH 13/13] vmdk: support vmfs files + +Message-id: <1377573001-27070-14-git-send-email-famz@redhat.com> +Patchwork-id: 53793 +O-Subject: [RHEL-7 qemu-kvm PATCH 13/13] vmdk: support vmfs files +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +VMware ESX hosts also use different create and extent types for flat +files, respectively "vmfs" and "VMFS". This is not documented, but it +can be found at http://kb.vmware.com/kb/10002511 (Recreating a missing +virtual machine disk (VMDK) descriptor file). + +Signed-off-by: Paolo Bonzini +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 04d542c8b826a1196ca4f03f5a35d83035976bd1) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 5 +++-- + 1 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 4d0c82a..b0b419b 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -719,7 +719,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + + if (sectors <= 0 || + (strcmp(type, "FLAT") && strcmp(type, "SPARSE") && +- strcmp(type, "VMFSSPARSE")) || ++ strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) || + (strcmp(access, "RW"))) { + goto next_line; + } +@@ -732,7 +732,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + } + + /* save to extents array */ +- if (!strcmp(type, "FLAT")) { ++ if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) { + /* FLAT extent */ + VmdkExtent *extent; + +@@ -790,6 +790,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + goto exit; + } + if (strcmp(ct, "monolithicFlat") && ++ strcmp(ct, "vmfs") && + strcmp(ct, "vmfsSparse") && + strcmp(ct, "twoGbMaxExtentSparse") && + strcmp(ct, "twoGbMaxExtentFlat")) { +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-support-vmfsSparse-files.patch b/SOURCES/kvm-vmdk-support-vmfsSparse-files.patch new file mode 100644 index 0000000..82ebf01 --- /dev/null +++ b/SOURCES/kvm-vmdk-support-vmfsSparse-files.patch @@ -0,0 +1,112 @@ +From 26c4eb4923589b410b1aec705b8665afb5e78794 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Mon, 19 Aug 2013 18:54:27 +0800 +Subject: [PATCH 12/13] vmdk: support vmfsSparse files + +Message-id: <1377573001-27070-13-git-send-email-famz@redhat.com> +Patchwork-id: 53792 +O-Subject: [RHEL-7 qemu-kvm PATCH 12/13] vmdk: support vmfsSparse files +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +VMware ESX hosts use a variant of the VMDK3 format, identified by the +vmfsSparse create type ad the VMFSSPARSE extent type. + +It has 16 KB grain tables (L2) and a variable-size grain directory (L1). +In addition, the grain size is always 512, but that is not a problem +because it is included in the header. + +The format of the extents is documented in the VMDK spec. The format +of the descriptor file is not documented precisely, but it can be +found at http://kb.vmware.com/kb/10026353 (Recreating a missing virtual +machine disk (VMDK) descriptor file for delta disks). + +With these patches, vmfsSparse files only work if opened through the +descriptor file. Data files without descriptor files, as far as I +could understand, are not supported by ESX. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Fam Zheng + +-- +v2: Rebase to patch 01. + Change le64_to_cpu to le32_to_cpu. + Rename vmdk_open_vmdk3 to vmdk_open_vmfs_sparse, which represents the + current usage of this format. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit daac8fdc68c5f0118ce24fcac5873ddaa0d0c9f9) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 17 +++++++++-------- + 1 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 4997da4..4d0c82a 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -481,9 +481,9 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) + return ret; + } + +-static int vmdk_open_vmdk3(BlockDriverState *bs, +- BlockDriverState *file, +- int flags) ++static int vmdk_open_vmfs_sparse(BlockDriverState *bs, ++ BlockDriverState *file, ++ int flags) + { + int ret; + uint32_t magic; +@@ -674,7 +674,7 @@ static int vmdk_open_sparse(BlockDriverState *bs, + magic = be32_to_cpu(magic); + switch (magic) { + case VMDK3_MAGIC: +- return vmdk_open_vmdk3(bs, file, flags); ++ return vmdk_open_vmfs_sparse(bs, file, flags); + break; + case VMDK4_MAGIC: + return vmdk_open_vmdk4(bs, file, flags); +@@ -718,7 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + } + + if (sectors <= 0 || +- (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) || ++ (strcmp(type, "FLAT") && strcmp(type, "SPARSE") && ++ strcmp(type, "VMFSSPARSE")) || + (strcmp(access, "RW"))) { + goto next_line; + } +@@ -741,8 +742,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, + return ret; + } + extent->flat_start_offset = flat_offset << 9; +- } else if (!strcmp(type, "SPARSE")) { +- /* SPARSE extent */ ++ } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) { ++ /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/ + ret = vmdk_open_sparse(bs, extent_file, bs->open_flags); + if (ret) { + bdrv_delete(extent_file); +@@ -789,6 +790,7 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + goto exit; + } + if (strcmp(ct, "monolithicFlat") && ++ strcmp(ct, "vmfsSparse") && + strcmp(ct, "twoGbMaxExtentSparse") && + strcmp(ct, "twoGbMaxExtentFlat")) { + fprintf(stderr, +@@ -1381,7 +1383,6 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, + return ret; + } + +- + static int vmdk_create_extent(const char *filename, int64_t filesize, + bool flat, bool compress, bool zeroed_grain) + { +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-use-heap-allocation-for-whole_grain.patch b/SOURCES/kvm-vmdk-use-heap-allocation-for-whole_grain.patch new file mode 100644 index 0000000..96dd431 --- /dev/null +++ b/SOURCES/kvm-vmdk-use-heap-allocation-for-whole_grain.patch @@ -0,0 +1,82 @@ +From 7762468560c9a2283836a4abdde58301ad7fb1cf Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:54 +0800 +Subject: [PATCH 08/13] vmdk: use heap allocation for whole_grain + +Message-id: <1377573001-27070-9-git-send-email-famz@redhat.com> +Patchwork-id: 53788 +O-Subject: [RHEL-7 qemu-kvm PATCH 08/13] vmdk: use heap allocation for + whole_grain +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +We should never grow the stack beyond 1 MB, otherwise we'll fall off the +end. Thread stacks and coroutine stacks (1 MB) do not grow. +get_cluster_offset() allocates a big stack offset, it will fail for big +cluster images, change to heap allocated buffer. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit bf81507de38fdfa4cb6e9b46fb38691a25cb1499) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 21 +++++++++++++-------- + 1 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index 58163ef..1af6122 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -842,16 +842,17 @@ static int get_whole_cluster(BlockDriverState *bs, + uint64_t offset, + bool allocate) + { +- /* 128 sectors * 512 bytes each = grain size 64KB */ +- uint8_t whole_grain[extent->cluster_sectors * 512]; ++ int ret = VMDK_OK; ++ uint8_t *whole_grain = NULL; + + /* we will be here if it's first write on non-exist grain(cluster). + * try to read from parent image, if exist */ + if (bs->backing_hd) { +- int ret; +- ++ whole_grain = ++ qemu_blockalign(bs, extent->cluster_sectors << BDRV_SECTOR_BITS); + if (!vmdk_is_cid_valid(bs)) { +- return VMDK_ERROR; ++ ret = VMDK_ERROR; ++ goto exit; + } + + /* floor offset to cluster */ +@@ -859,17 +860,21 @@ static int get_whole_cluster(BlockDriverState *bs, + ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain, + extent->cluster_sectors); + if (ret < 0) { +- return VMDK_ERROR; ++ ret = VMDK_ERROR; ++ goto exit; + } + + /* Write grain only into the active image */ + ret = bdrv_write(extent->file, cluster_offset, whole_grain, + extent->cluster_sectors); + if (ret < 0) { +- return VMDK_ERROR; ++ ret = VMDK_ERROR; ++ goto exit; + } + } +- return VMDK_OK; ++exit: ++ qemu_vfree(whole_grain); ++ return ret; + } + + static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data) +-- +1.7.1 + diff --git a/SOURCES/kvm-vmdk-use-unsigned-values-for-on-disk-header-fields.patch b/SOURCES/kvm-vmdk-use-unsigned-values-for-on-disk-header-fields.patch new file mode 100644 index 0000000..596028e --- /dev/null +++ b/SOURCES/kvm-vmdk-use-unsigned-values-for-on-disk-header-fields.patch @@ -0,0 +1,91 @@ +From 1826fdaaacd0d6898bb3bd64935edd520dd95428 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Tue, 6 Aug 2013 15:44:48 +0800 +Subject: [PATCH 02/13] vmdk: use unsigned values for on disk header fields + +Message-id: <1377573001-27070-3-git-send-email-famz@redhat.com> +Patchwork-id: 53782 +O-Subject: [RHEL-7 qemu-kvm PATCH 02/13] vmdk: use unsigned values for on disk + header fields +Bugzilla: 995866 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +The size and offset fields are all non-negative values, use uint64_t for +them to avoid getting negative in memory value by int overflow. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit e98768d43799cd3f00b358bfbe455fdae793d3e8) +Signed-off-by: Fam Zheng +--- + block/vmdk.c | 24 ++++++++++++------------ + 1 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/block/vmdk.c b/block/vmdk.c +index e85f4ea..78ea480 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -67,14 +67,14 @@ typedef struct { + typedef struct { + uint32_t version; + uint32_t flags; +- int64_t capacity; +- int64_t granularity; +- int64_t desc_offset; +- int64_t desc_size; +- int32_t num_gtes_per_gte; +- int64_t rgd_offset; +- int64_t gd_offset; +- int64_t grain_offset; ++ uint64_t capacity; ++ uint64_t granularity; ++ uint64_t desc_offset; ++ uint64_t desc_size; ++ uint32_t num_gtes_per_gte; ++ uint64_t rgd_offset; ++ uint64_t gd_offset; ++ uint64_t grain_offset; + char filler[1]; + char check_bytes[4]; + uint16_t compressAlgorithm; +@@ -109,7 +109,7 @@ typedef struct VmdkExtent { + + typedef struct BDRVVmdkState { + CoMutex lock; +- int desc_offset; ++ uint64_t desc_offset; + bool cid_updated; + uint32_t parent_cid; + int num_extents; +@@ -490,7 +490,7 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, + } + + static int vmdk_open_desc_file(BlockDriverState *bs, int flags, +- int64_t desc_offset); ++ uint64_t desc_offset); + + static int vmdk_open_vmdk4(BlockDriverState *bs, + BlockDriverState *file, +@@ -508,7 +508,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + return ret; + } + if (header.capacity == 0) { +- int64_t desc_offset = le64_to_cpu(header.desc_offset); ++ uint64_t desc_offset = le64_to_cpu(header.desc_offset); + if (desc_offset) { + return vmdk_open_desc_file(bs, flags, desc_offset << 9); + } +@@ -728,7 +728,7 @@ next_line: + } + + static int vmdk_open_desc_file(BlockDriverState *bs, int flags, +- int64_t desc_offset) ++ uint64_t desc_offset) + { + int ret; + char *buf = NULL; +-- +1.7.1 + diff --git a/SOURCES/kvm-vt82c686-Clean-up-use-of-cannot_instantiate_with_dev.patch b/SOURCES/kvm-vt82c686-Clean-up-use-of-cannot_instantiate_with_dev.patch new file mode 100644 index 0000000..d29eebd --- /dev/null +++ b/SOURCES/kvm-vt82c686-Clean-up-use-of-cannot_instantiate_with_dev.patch @@ -0,0 +1,73 @@ +From 86a622181cfcb4205877595fa53b3bbc87cf9431 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 6 Nov 2013 14:41:19 +0100 +Subject: [PATCH 43/81] vt82c686: Clean up use of cannot_instantiate_with_device_add_yet + +RH-Author: Kevin Wolf +Message-id: <1383748882-22831-15-git-send-email-kwolf@redhat.com> +Patchwork-id: 55540 +O-Subject: [RHEL-7.0 qemu-kvm PATCH v2 14/17] vt82c686: Clean up use of cannot_instantiate_with_device_add_yet +Bugzilla: 1001216 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Kevin Wolf +RH-Acked-by: Miroslav Rezanina + +From: Markus Armbruster + +A VT82C686B southbridge has multiple functions. We model each +function as a separate qdev. One of them need some special wiring set +up in mips_fulong2e_init() to work: the ISA bridge at 05.0. + +The IDE controller at 05.1 (via-ide) has always had +cannot_instantiate_with_device_add_yet set, but there is no obvious +reason why device_add could not work for them. Drop it. + +Signed-off-by: Markus Armbruster +Reviewed-by: Peter Maydell +(cherry picked from pending upstream submission) +Signed-off-by: Kevin Wolf +--- + hw/ide/via.c | 1 - + hw/isa/vt82c686.c | 6 +++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/ide/via.c | 1 - + hw/isa/vt82c686.c | 6 +++++- + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/hw/ide/via.c b/hw/ide/via.c +index 6ba99c8..326722c 100644 +--- a/hw/ide/via.c ++++ b/hw/ide/via.c +@@ -224,7 +224,6 @@ static void via_ide_class_init(ObjectClass *klass, void *data) + k->revision = 0x06; + k->class_id = PCI_CLASS_STORAGE_IDE; + set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + } + + static const TypeInfo via_ide_info = { +diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c +index 563e154..bb84414 100644 +--- a/hw/isa/vt82c686.c ++++ b/hw/isa/vt82c686.c +@@ -468,8 +468,12 @@ static void via_class_init(ObjectClass *klass, void *data) + k->class_id = PCI_CLASS_BRIDGE_ISA; + k->revision = 0x40; + dc->desc = "ISA bridge"; +- dc->cannot_instantiate_with_device_add_yet = true; /* FIXME explain why */ + dc->vmsd = &vmstate_via; ++ /* ++ * Reason: part of VIA VT82C686 southbridge, needs to be wired up, ++ * e.g. by mips_fulong2e_init() ++ */ ++ dc->cannot_instantiate_with_device_add_yet = true; + } + + static const TypeInfo via_info = { +-- +1.7.1 + diff --git a/SOURCES/kvm-w32-Fix-access-to-host-devices-regression.patch b/SOURCES/kvm-w32-Fix-access-to-host-devices-regression.patch new file mode 100644 index 0000000..26f0611 --- /dev/null +++ b/SOURCES/kvm-w32-Fix-access-to-host-devices-regression.patch @@ -0,0 +1,108 @@ +From c9f57b61fd600b60276a1f50be5af3eed7d8bafd Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Mon, 4 Nov 2013 22:32:07 +0100 +Subject: [PATCH 14/87] w32: Fix access to host devices (regression) + +RH-Author: Max Reitz +Message-id: <1383604354-12743-17-git-send-email-mreitz@redhat.com> +Patchwork-id: 55316 +O-Subject: [RHEL-7.0 qemu-kvm PATCH 16/43] w32: Fix access to host devices (regression) +Bugzilla: 1026524 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Fam Zheng +RH-Acked-by: Stefan Hajnoczi + +From: Stefan Weil + +BZ: 1026524 + +QEMU failed to open host devices like \\.\PhysicalDrive0 (first hard disk) +since some time (commit 8a79380b8ef1b02d2abd705dd026a18863b09020?). + +Those devices use hdev_open which did not use the latest API for options. +This resulted in a fatal runtime error: + + Block protocol 'host_device' doesn't support the option 'filename' + +Duplicate code from raw_open to fix this. + +Cc: qemu-stable@nongnu.org +Reported-by: David Brenner +Signed-off-by: Stefan Weil +Reviewed-by: Kevin Wolf +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 68dc036488dfea170627a55e6ee3dfd7f2c2063e) + +Signed-off-by: Max Reitz +--- + block/raw-win32.c | 36 +++++++++++++++++++++++++++++------- + 1 file changed, 29 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + block/raw-win32.c | 36 +++++++++++++++++++++++++++++------- + 1 files changed, 29 insertions(+), 7 deletions(-) + +diff --git a/block/raw-win32.c b/block/raw-win32.c +index 7c03b6d..a324e5b 100644 +--- a/block/raw-win32.c ++++ b/block/raw-win32.c +@@ -534,13 +534,29 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags) + { + BDRVRawState *s = bs->opaque; + int access_flags, create_flags; ++ int ret = 0; + DWORD overlapped; + char device_name[64]; +- const char *filename = qdict_get_str(options, "filename"); ++ ++ Error *local_err = NULL; ++ const char *filename; ++ ++ QemuOpts *opts = qemu_opts_create_nofail(&raw_runtime_opts); ++ qemu_opts_absorb_qdict(opts, options, &local_err); ++ if (error_is_set(&local_err)) { ++ qerror_report_err(local_err); ++ error_free(local_err); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ filename = qemu_opt_get(opts, "filename"); + + if (strstart(filename, "/dev/cdrom", NULL)) { +- if (find_cdrom(device_name, sizeof(device_name)) < 0) +- return -ENOENT; ++ if (find_cdrom(device_name, sizeof(device_name)) < 0) { ++ ret = -ENOENT; ++ goto done; ++ } + filename = device_name; + } else { + /* transform drive letters into device name */ +@@ -563,11 +579,17 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags) + if (s->hfile == INVALID_HANDLE_VALUE) { + int err = GetLastError(); + +- if (err == ERROR_ACCESS_DENIED) +- return -EACCES; +- return -1; ++ if (err == ERROR_ACCESS_DENIED) { ++ ret = -EACCES; ++ } else { ++ ret = -1; ++ } ++ goto done; + } +- return 0; ++ ++done: ++ qemu_opts_del(opts); ++ return ret; + } + + static int hdev_has_zero_init(BlockDriverState *bs) +-- +1.7.1 + diff --git a/SOURCES/kvm-warn-if-num-cpus-is-greater-than-num-recommended.patch b/SOURCES/kvm-warn-if-num-cpus-is-greater-than-num-recommended.patch new file mode 100644 index 0000000..683b7eb --- /dev/null +++ b/SOURCES/kvm-warn-if-num-cpus-is-greater-than-num-recommended.patch @@ -0,0 +1,146 @@ +From 453a94cf85a041792086990022d182bcc4f939cb Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Tue, 24 Sep 2013 13:29:36 +0200 +Subject: [PATCH 05/11] kvm: warn if num cpus is greater than num recommended + +RH-Author: Andrew Jones +Message-id: <1380029376-20391-1-git-send-email-drjones@redhat.com> +Patchwork-id: 54526 +O-Subject: [RHEL7.0 qemu-kvm PATCH] kvm: warn if num cpus is greater than num recommended +Bugzilla: 1010881 +RH-Acked-by: Radim Krcmar +RH-Acked-by: Igor Mammedov +RH-Acked-by: Miroslav Rezanina + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1010881 +Brewing: https://brewweb.devel.redhat.com/taskinfo?taskID=6322066 + +(cherry picked from commit 670436ced08738802e15764039d03ab0dbab2bf3 + of uq/master) + +=== + +The comment in kvm_max_vcpus() states that it's using the recommended +procedure from the kernel API documentation to get the max number +of vcpus that kvm supports. It is, but by always returning the +maximum number supported. The maximum number should only be used +for development purposes. qemu should check KVM_CAP_NR_VCPUS for +the recommended number of vcpus. This patch adds a warning if a user +specifies a number of cpus between the recommended and max. + +Signed-off-by: Andrew Jones +Acked-by: Marcelo Tosatti +Signed-off-by: Gleb Natapov +--- + kvm-all.c | 69 ++++++++++++++++++++++++++++++++++++--------------------------- + 1 file changed, 40 insertions(+), 29 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + kvm-all.c | 69 +++++++++++++++++++++++++++++++++++------------------------- + 1 files changed, 40 insertions(+), 29 deletions(-) + +diff --git a/kvm-all.c b/kvm-all.c +index d0a7c21..f2f68d6 100644 +--- a/kvm-all.c ++++ b/kvm-all.c +@@ -1280,24 +1280,20 @@ static int kvm_irqchip_create(KVMState *s) + return 0; + } + +-static int kvm_max_vcpus(KVMState *s) ++/* Find number of supported CPUs using the recommended ++ * procedure from the kernel API documentation to cope with ++ * older kernels that may be missing capabilities. ++ */ ++static int kvm_recommended_vcpus(KVMState *s) + { +- int ret; +- +- /* Find number of supported CPUs using the recommended +- * procedure from the kernel API documentation to cope with +- * older kernels that may be missing capabilities. +- */ +- ret = kvm_check_extension(s, KVM_CAP_MAX_VCPUS); +- if (ret) { +- return ret; +- } +- ret = kvm_check_extension(s, KVM_CAP_NR_VCPUS); +- if (ret) { +- return ret; +- } ++ int ret = kvm_check_extension(s, KVM_CAP_NR_VCPUS); ++ return (ret) ? ret : 4; ++} + +- return 4; ++static int kvm_max_vcpus(KVMState *s) ++{ ++ int ret = kvm_check_extension(s, KVM_CAP_MAX_VCPUS); ++ return (ret) ? ret : kvm_recommended_vcpus(s); + } + + int kvm_init(void) +@@ -1305,11 +1301,19 @@ int kvm_init(void) + static const char upgrade_note[] = + "Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n" + "(see http://sourceforge.net/projects/kvm).\n"; ++ struct { ++ const char *name; ++ int num; ++ } num_cpus[] = { ++ { "SMP", smp_cpus }, ++ { "hotpluggable", max_cpus }, ++ { NULL, } ++ }, *nc = num_cpus; ++ int soft_vcpus_limit, hard_vcpus_limit; + KVMState *s; + const KVMCapabilityInfo *missing_cap; + int ret; + int i; +- int max_vcpus; + + s = g_malloc0(sizeof(KVMState)); + +@@ -1350,19 +1354,26 @@ int kvm_init(void) + goto err; + } + +- max_vcpus = kvm_max_vcpus(s); +- if (smp_cpus > max_vcpus) { +- ret = -EINVAL; +- fprintf(stderr, "Number of SMP cpus requested (%d) exceeds max cpus " +- "supported by KVM (%d)\n", smp_cpus, max_vcpus); +- goto err; +- } ++ /* check the vcpu limits */ ++ soft_vcpus_limit = kvm_recommended_vcpus(s); ++ hard_vcpus_limit = kvm_max_vcpus(s); + +- if (max_cpus > max_vcpus) { +- ret = -EINVAL; +- fprintf(stderr, "Number of hotpluggable cpus requested (%d) exceeds max cpus " +- "supported by KVM (%d)\n", max_cpus, max_vcpus); +- goto err; ++ while (nc->name) { ++ if (nc->num > soft_vcpus_limit) { ++ fprintf(stderr, ++ "Warning: Number of %s cpus requested (%d) exceeds " ++ "the recommended cpus supported by KVM (%d)\n", ++ nc->name, nc->num, soft_vcpus_limit); ++ ++ if (nc->num > hard_vcpus_limit) { ++ ret = -EINVAL; ++ fprintf(stderr, "Number of %s cpus requested (%d) exceeds " ++ "the maximum cpus supported by KVM (%d)\n", ++ nc->name, nc->num, hard_vcpus_limit); ++ goto err; ++ } ++ } ++ nc++; + } + + s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0); +-- +1.7.1 + diff --git a/SOURCES/kvm-x86-cpuid-reconstruct-leaf-0Dh-data.patch b/SOURCES/kvm-x86-cpuid-reconstruct-leaf-0Dh-data.patch new file mode 100644 index 0000000..f1aad1e --- /dev/null +++ b/SOURCES/kvm-x86-cpuid-reconstruct-leaf-0Dh-data.patch @@ -0,0 +1,122 @@ +From 1a92e9ba72edd6386d35cf4894b7b83ea3279cff Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 5 Nov 2013 15:10:44 +0100 +Subject: [PATCH 53/81] x86: cpuid: reconstruct leaf 0Dh data + +RH-Author: Paolo Bonzini +Message-id: <1383664244-14818-3-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55409 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 2/2] x86: cpuid: reconstruct leaf 0Dh data +Bugzilla: 1005695 +RH-Acked-by: Alex Williamson +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eduardo Habkost + +The data in leaf 0Dh depends on information from other feature bits. +Instead of passing it blindly from the host, compute it based on +whether these feature bits are enabled. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Gleb Natapov +(cherry picked from commit 2560f19f426aceb4f2e809d860b93e7573cb1c4e) +--- + target-i386/cpu.c | 65 ++++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 48 insertions(+), 17 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 65 +++++++++++++++++++++++++++++++++++++++-------------- + 1 files changed, 48 insertions(+), 17 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index bc077ca..42105aa 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -218,6 +218,15 @@ X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { + }; + #undef REGISTER + ++typedef struct ExtSaveArea { ++ uint32_t feature, bits; ++ uint32_t offset, size; ++} ExtSaveArea; ++ ++static const ExtSaveArea ext_save_areas[] = { ++ [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, ++ .offset = 0x100, .size = 0x240 }, ++}; + + const char *get_register_name_32(unsigned int reg) + { +@@ -2061,29 +2070,51 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + *edx = 0; + } + break; +- case 0xD: ++ case 0xD: { ++ KVMState *s = cs->kvm_state; ++ uint64_t kvm_mask; ++ int i; ++ + /* Processor Extended State */ +- if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { +- *eax = 0; +- *ebx = 0; +- *ecx = 0; +- *edx = 0; ++ *eax = 0; ++ *ebx = 0; ++ *ecx = 0; ++ *edx = 0; ++ if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) { + break; + } +- if (kvm_enabled()) { +- KVMState *s = cs->kvm_state; ++ kvm_mask = ++ kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX) | ++ ((uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32); + +- *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); +- *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); +- *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); +- *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); +- } else { +- *eax = 0; +- *ebx = 0; +- *ecx = 0; +- *edx = 0; ++ if (count == 0) { ++ *ecx = 0x240; ++ for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) { ++ const ExtSaveArea *esa = &ext_save_areas[i]; ++ if ((env->features[esa->feature] & esa->bits) == esa->bits && ++ (kvm_mask & (1 << i)) != 0) { ++ if (i < 32) { ++ *eax |= 1 << i; ++ } else { ++ *edx |= 1 << (i - 32); ++ } ++ *ecx = MAX(*ecx, esa->offset + esa->size); ++ } ++ } ++ *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE); ++ *ebx = *ecx; ++ } else if (count == 1) { ++ *eax = kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX); ++ } else if (count < ARRAY_SIZE(ext_save_areas)) { ++ 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; ++ } + } + break; ++ } + case 0x80000000: + *eax = env->cpuid_xlevel; + *ebx = env->cpuid_vendor1; +-- +1.7.1 + diff --git a/SOURCES/kvm-x86-fix-migration-from-pre-version-12.patch b/SOURCES/kvm-x86-fix-migration-from-pre-version-12.patch new file mode 100644 index 0000000..e4e9e59 --- /dev/null +++ b/SOURCES/kvm-x86-fix-migration-from-pre-version-12.patch @@ -0,0 +1,65 @@ +From 8328cafa2406bcfed728c236fce8e5121f6c0b6d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Tue, 5 Nov 2013 15:10:43 +0100 +Subject: [PATCH 52/81] x86: fix migration from pre-version 12 + +RH-Author: Paolo Bonzini +Message-id: <1383664244-14818-2-git-send-email-pbonzini@redhat.com> +Patchwork-id: 55408 +O-Subject: [RHEL 7.0 qemu-kvm PATCH 1/2] x86: fix migration from pre-version 12 +Bugzilla: 1005695 +RH-Acked-by: Alex Williamson +RH-Acked-by: Orit Wasserman +RH-Acked-by: Eduardo Habkost + +On KVM, the KVM_SET_XSAVE would be executed with a 0 xstate_bv, +and not restore anything. + +Since FP and SSE data are always valid, set them in xstate_bv at reset +time. In fact, that value is the same that KVM_GET_XSAVE returns on +pre-XSAVE hosts. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Gleb Natapov +(cherry picked from commit c74f41bbcc83d12787ac42f2c74fc2be54e9f222) +--- + target-i386/cpu.c | 1 + + target-i386/cpu.h | 4 ++++ + 2 files changed, 5 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + target-i386/cpu.c | 1 + + target-i386/cpu.h | 4 ++++ + 2 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 170a46c..bc077ca 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -2269,6 +2269,7 @@ static void x86_cpu_reset(CPUState *s) + env->fpuc = 0x37f; + + env->mxcsr = 0x1f80; ++ env->xstate_bv = XSTATE_FP | XSTATE_SSE; + + env->pat = 0x0007040600070406ULL; + env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT; +diff --git a/target-i386/cpu.h b/target-i386/cpu.h +index 6aebc80..9c55953 100644 +--- a/target-i386/cpu.h ++++ b/target-i386/cpu.h +@@ -379,6 +379,10 @@ + + #define MSR_VM_HSAVE_PA 0xc0010117 + ++#define XSTATE_FP 1 ++#define XSTATE_SSE 2 ++#define XSTATE_YMM 4 ++ + /* CPUID feature words */ + typedef enum FeatureWord { + FEAT_1_EDX, /* CPUID[1].EDX */ +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-add-XHCISlot-addressed.patch b/SOURCES/kvm-xhci-add-XHCISlot-addressed.patch new file mode 100644 index 0000000..9b0a5d6 --- /dev/null +++ b/SOURCES/kvm-xhci-add-XHCISlot-addressed.patch @@ -0,0 +1,58 @@ +From 4092201c71c55673c526887b3985002d8a9ba2d9 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:22:45 +0200 +Subject: [PATCH 14/28] xhci: add XHCISlot->addressed + +RH-Author: Gerd Hoffmann +Message-id: <1375867368-18979-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 53039 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/5] xhci: add XHCISlot->addressed +Bugzilla: 838170 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Orit Wasserman + +Preparing for live-migration support, post_load will need that. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 4034e6938a4cba090a8fac02499c8a9567201665) +--- + hw/usb/hcd-xhci.c | 3 +++ + 1 file changed, 3 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index d88c1ae..4111e68 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -405,6 +405,7 @@ struct XHCIEPContext { + + typedef struct XHCISlot { + bool enabled; ++ bool addressed; + dma_addr_t ctx; + USBPort *uport; + XHCIEPContext * eps[31]; +@@ -2041,6 +2042,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) + } + + xhci->slots[slotid-1].enabled = 0; ++ xhci->slots[slotid-1].addressed = 0; + return CC_SUCCESS; + } + +@@ -2167,6 +2169,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, + xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx)); + xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx)); + ++ xhci->slots[slotid-1].addressed = 1; + return res; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-add-live-migration-support.patch b/SOURCES/kvm-xhci-add-live-migration-support.patch new file mode 100644 index 0000000..85c1820 --- /dev/null +++ b/SOURCES/kvm-xhci-add-live-migration-support.patch @@ -0,0 +1,208 @@ +From e07526dd14669081a569bb6b1e3d72e1ee59ebad Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:22:48 +0200 +Subject: [PATCH 17/28] xhci: add live migration support + +RH-Author: Gerd Hoffmann +Message-id: <1375867368-18979-6-git-send-email-kraxel@redhat.com> +Patchwork-id: 53041 +O-Subject: [RHEL-7 qemu-kvm PATCH 5/5] xhci: add live migration support +Bugzilla: 838170 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Orit Wasserman + +With all preparing pieces in place we can finally drop in +the vmstate structs and the postload function. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 37352df30fbc38d1de464db8927536d5e36cf52a) +--- + hw/usb/hcd-xhci.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 163 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 163 insertions(+), 1 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 8224465..3d3d6c3 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -3386,9 +3386,171 @@ static int usb_xhci_initfn(struct PCIDevice *dev) + return 0; + } + ++static int usb_xhci_post_load(void *opaque, int version_id) ++{ ++ XHCIState *xhci = opaque; ++ XHCISlot *slot; ++ XHCIEPContext *epctx; ++ dma_addr_t dcbaap, pctx; ++ uint32_t slot_ctx[4]; ++ uint32_t ep_ctx[5]; ++ int slotid, epid, state, intr; ++ ++ dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); ++ ++ for (slotid = 1; slotid <= xhci->numslots; slotid++) { ++ slot = &xhci->slots[slotid-1]; ++ if (!slot->addressed) { ++ continue; ++ } ++ slot->ctx = ++ xhci_mask64(ldq_le_pci_dma(&xhci->pci_dev, dcbaap + 8*slotid)); ++ xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx)); ++ slot->uport = xhci_lookup_uport(xhci, slot_ctx); ++ assert(slot->uport && slot->uport->dev); ++ ++ for (epid = 1; epid <= 32; epid++) { ++ pctx = slot->ctx + 32 * epid; ++ xhci_dma_read_u32s(xhci, pctx, ep_ctx, sizeof(ep_ctx)); ++ state = ep_ctx[0] & EP_STATE_MASK; ++ if (state == EP_DISABLED) { ++ continue; ++ } ++ epctx = xhci_alloc_epctx(xhci, slotid, epid); ++ slot->eps[epid-1] = epctx; ++ xhci_init_epctx(epctx, pctx, ep_ctx); ++ epctx->state = state; ++ if (state == EP_RUNNING) { ++ /* kick endpoint after vmload is finished */ ++ qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock)); ++ } ++ } ++ } ++ ++ for (intr = 0; intr < xhci->numintrs; intr++) { ++ if (xhci->intr[intr].msix_used) { ++ msix_vector_use(&xhci->pci_dev, intr); ++ } else { ++ msix_vector_unuse(&xhci->pci_dev, intr); ++ } ++ } ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_xhci_ring = { ++ .name = "xhci-ring", ++ .version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(dequeue, XHCIRing), ++ VMSTATE_BOOL(ccs, XHCIRing), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_xhci_port = { ++ .name = "xhci-port", ++ .version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(portsc, XHCIPort), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_xhci_slot = { ++ .name = "xhci-slot", ++ .version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_BOOL(enabled, XHCISlot), ++ VMSTATE_BOOL(addressed, XHCISlot), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static const VMStateDescription vmstate_xhci_event = { ++ .name = "xhci-event", ++ .version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(type, XHCIEvent), ++ VMSTATE_UINT32(ccode, XHCIEvent), ++ VMSTATE_UINT64(ptr, XHCIEvent), ++ VMSTATE_UINT32(length, XHCIEvent), ++ VMSTATE_UINT32(flags, XHCIEvent), ++ VMSTATE_UINT8(slotid, XHCIEvent), ++ VMSTATE_UINT8(epid, XHCIEvent), ++ } ++}; ++ ++static bool xhci_er_full(void *opaque, int version_id) ++{ ++ struct XHCIInterrupter *intr = opaque; ++ return intr->er_full; ++} ++ ++static const VMStateDescription vmstate_xhci_intr = { ++ .name = "xhci-intr", ++ .version_id = 1, ++ .fields = (VMStateField[]) { ++ /* registers */ ++ VMSTATE_UINT32(iman, XHCIInterrupter), ++ VMSTATE_UINT32(imod, XHCIInterrupter), ++ VMSTATE_UINT32(erstsz, XHCIInterrupter), ++ VMSTATE_UINT32(erstba_low, XHCIInterrupter), ++ VMSTATE_UINT32(erstba_high, XHCIInterrupter), ++ VMSTATE_UINT32(erdp_low, XHCIInterrupter), ++ VMSTATE_UINT32(erdp_high, XHCIInterrupter), ++ ++ /* state */ ++ VMSTATE_BOOL(msix_used, XHCIInterrupter), ++ VMSTATE_BOOL(er_pcs, XHCIInterrupter), ++ VMSTATE_UINT64(er_start, XHCIInterrupter), ++ VMSTATE_UINT32(er_size, XHCIInterrupter), ++ VMSTATE_UINT32(er_ep_idx, XHCIInterrupter), ++ ++ /* event queue (used if ring is full) */ ++ VMSTATE_BOOL(er_full, XHCIInterrupter), ++ VMSTATE_UINT32_TEST(ev_buffer_put, XHCIInterrupter, xhci_er_full), ++ VMSTATE_UINT32_TEST(ev_buffer_get, XHCIInterrupter, xhci_er_full), ++ VMSTATE_STRUCT_ARRAY_TEST(ev_buffer, XHCIInterrupter, EV_QUEUE, ++ xhci_er_full, 1, ++ vmstate_xhci_event, XHCIEvent), ++ ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_xhci = { + .name = "xhci", +- .unmigratable = 1, ++ .version_id = 1, ++ .post_load = usb_xhci_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_PCIE_DEVICE(pci_dev, XHCIState), ++ VMSTATE_MSIX(pci_dev, XHCIState), ++ ++ VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1, ++ vmstate_xhci_port, XHCIPort), ++ VMSTATE_STRUCT_VARRAY_UINT32(slots, XHCIState, numslots, 1, ++ vmstate_xhci_slot, XHCISlot), ++ VMSTATE_STRUCT_VARRAY_UINT32(intr, XHCIState, numintrs, 1, ++ vmstate_xhci_intr, XHCIInterrupter), ++ ++ /* Operational Registers */ ++ VMSTATE_UINT32(usbcmd, XHCIState), ++ VMSTATE_UINT32(usbsts, XHCIState), ++ VMSTATE_UINT32(dnctrl, XHCIState), ++ VMSTATE_UINT32(crcr_low, XHCIState), ++ VMSTATE_UINT32(crcr_high, XHCIState), ++ VMSTATE_UINT32(dcbaap_low, XHCIState), ++ VMSTATE_UINT32(dcbaap_high, XHCIState), ++ VMSTATE_UINT32(config, XHCIState), ++ ++ /* Runtime Registers & state */ ++ VMSTATE_INT64(mfindex_start, XHCIState), ++ VMSTATE_TIMER(mfwrap_timer, XHCIState), ++ VMSTATE_STRUCT(cmd_ring, XHCIState, 1, vmstate_xhci_ring, XHCIRing), ++ ++ VMSTATE_END_OF_LIST() ++ } + }; + + static Property xhci_properties[] = { +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-add-xhci_alloc_epctx.patch b/SOURCES/kvm-xhci-add-xhci_alloc_epctx.patch new file mode 100644 index 0000000..50d8638 --- /dev/null +++ b/SOURCES/kvm-xhci-add-xhci_alloc_epctx.patch @@ -0,0 +1,98 @@ +From e955b37a28ff1f10035dc9c96a083bf93e8ca895 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:22:46 +0200 +Subject: [PATCH 15/28] xhci: add xhci_alloc_epctx + +RH-Author: Gerd Hoffmann +Message-id: <1375867368-18979-4-git-send-email-kraxel@redhat.com> +Patchwork-id: 53036 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/5] xhci: add xhci_alloc_epctx +Bugzilla: 838170 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Orit Wasserman + +Factor out endpoint context allocation to a separate function. +xhci live migration will need that too, in post_load. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 492b21f63fa655e0271abef4784cc337dd1d3fe7) +--- + hw/usb/hcd-xhci.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 32 +++++++++++++++++++++----------- + 1 files changed, 21 insertions(+), 11 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 4111e68..7f46ccc 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -1198,6 +1198,26 @@ static void xhci_ep_kick_timer(void *opaque) + xhci_kick_ep(epctx->xhci, epctx->slotid, epctx->epid, 0); + } + ++static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci, ++ unsigned int slotid, ++ unsigned int epid) ++{ ++ XHCIEPContext *epctx; ++ int i; ++ ++ epctx = g_new0(XHCIEPContext, 1); ++ epctx->xhci = xhci; ++ epctx->slotid = slotid; ++ epctx->epid = epid; ++ ++ for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) { ++ usb_packet_init(&epctx->transfers[i].packet); ++ } ++ epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx); ++ ++ return epctx; ++} ++ + static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, + unsigned int epid, dma_addr_t pctx, + uint32_t *ctx) +@@ -1205,7 +1225,6 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, + XHCISlot *slot; + XHCIEPContext *epctx; + dma_addr_t dequeue; +- int i; + + trace_usb_xhci_ep_enable(slotid, epid); + assert(slotid >= 1 && slotid <= xhci->numslots); +@@ -1216,12 +1235,7 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, + xhci_disable_ep(xhci, slotid, epid); + } + +- epctx = g_malloc(sizeof(XHCIEPContext)); +- memset(epctx, 0, sizeof(XHCIEPContext)); +- epctx->xhci = xhci; +- epctx->slotid = slotid; +- epctx->epid = epid; +- ++ epctx = xhci_alloc_epctx(xhci, slotid, epid); + slot->eps[epid-1] = epctx; + + dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]); +@@ -1241,13 +1255,9 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, + xhci_ring_init(xhci, &epctx->ring, dequeue); + epctx->ring.ccs = ctx[2] & 1; + } +- for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) { +- usb_packet_init(&epctx->transfers[i].packet); +- } + + epctx->interval = 1 << (ctx[0] >> 16) & 0xff; + epctx->mfindex_last = 0; +- epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx); + + epctx->state = EP_RUNNING; + ctx[0] &= ~EP_STATE_MASK; +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-add-xhci_init_epctx.patch b/SOURCES/kvm-xhci-add-xhci_init_epctx.patch new file mode 100644 index 0000000..13a6a80 --- /dev/null +++ b/SOURCES/kvm-xhci-add-xhci_init_epctx.patch @@ -0,0 +1,99 @@ +From 6b9188baee63673ee4816b7bb994a7be3e164fce Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 7 Aug 2013 09:22:47 +0200 +Subject: [PATCH 16/28] xhci: add xhci_init_epctx + +RH-Author: Gerd Hoffmann +Message-id: <1375867368-18979-5-git-send-email-kraxel@redhat.com> +Patchwork-id: 53037 +O-Subject: [RHEL-7 qemu-kvm PATCH 4/5] xhci: add xhci_init_epctx +Bugzilla: 838170 +RH-Acked-by: Hans de Goede +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Orit Wasserman + +Factor out endpoint context initialization to a separate function. +xhci live migration will need that too, in post_load. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 003e15a180373048f0c1f4df0bfe303746eb2676) +--- + hw/usb/hcd-xhci.c | 43 +++++++++++++++++++++++++------------------ + 1 file changed, 25 insertions(+), 18 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 43 +++++++++++++++++++++++++------------------ + 1 files changed, 25 insertions(+), 18 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 7f46ccc..8224465 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -1218,26 +1218,11 @@ static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci, + return epctx; + } + +-static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, +- unsigned int epid, dma_addr_t pctx, +- uint32_t *ctx) ++static void xhci_init_epctx(XHCIEPContext *epctx, ++ dma_addr_t pctx, uint32_t *ctx) + { +- XHCISlot *slot; +- XHCIEPContext *epctx; + dma_addr_t dequeue; + +- trace_usb_xhci_ep_enable(slotid, epid); +- assert(slotid >= 1 && slotid <= xhci->numslots); +- assert(epid >= 1 && epid <= 31); +- +- slot = &xhci->slots[slotid-1]; +- if (slot->eps[epid-1]) { +- xhci_disable_ep(xhci, slotid, epid); +- } +- +- epctx = xhci_alloc_epctx(xhci, slotid, epid); +- slot->eps[epid-1] = epctx; +- + dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]); + + epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK; +@@ -1252,11 +1237,33 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, + if (epctx->max_pstreams) { + xhci_alloc_streams(epctx, dequeue); + } else { +- xhci_ring_init(xhci, &epctx->ring, dequeue); ++ xhci_ring_init(epctx->xhci, &epctx->ring, dequeue); + epctx->ring.ccs = ctx[2] & 1; + } + + epctx->interval = 1 << (ctx[0] >> 16) & 0xff; ++} ++ ++static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, ++ unsigned int epid, dma_addr_t pctx, ++ uint32_t *ctx) ++{ ++ XHCISlot *slot; ++ XHCIEPContext *epctx; ++ ++ trace_usb_xhci_ep_enable(slotid, epid); ++ assert(slotid >= 1 && slotid <= xhci->numslots); ++ assert(epid >= 1 && epid <= 31); ++ ++ slot = &xhci->slots[slotid-1]; ++ if (slot->eps[epid-1]) { ++ xhci_disable_ep(xhci, slotid, epid); ++ } ++ ++ epctx = xhci_alloc_epctx(xhci, slotid, epid); ++ slot->eps[epid-1] = epctx; ++ xhci_init_epctx(epctx, pctx, ctx); ++ + epctx->mfindex_last = 0; + + epctx->state = EP_RUNNING; +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-emulate-intr-endpoint-intervals-correctly.patch b/SOURCES/kvm-xhci-emulate-intr-endpoint-intervals-correctly.patch new file mode 100644 index 0000000..cf26ef6 --- /dev/null +++ b/SOURCES/kvm-xhci-emulate-intr-endpoint-intervals-correctly.patch @@ -0,0 +1,146 @@ +From e25b1bfc8a6b74bf8474fe8d8e927abd1cacaa4f Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 12 Sep 2013 09:39:30 +0200 +Subject: [PATCH 02/25] xhci: emulate intr endpoint intervals correctly + +RH-Author: Gerd Hoffmann +Message-id: <1378978772-21612-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 54337 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/4] xhci: emulate intr endpoint intervals correctly +Bugzilla: 1001604 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Hans de Goede +RH-Acked-by: Miroslav Rezanina + +Respect the interval for interrupt endpoints, so we don't finish +transfers as fast as possible but at the rate configured by the guest. + +Fixes guest deadlocks triggered by interrupt storms. + +Cc: +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 4d7a81c06f5f17e019a2d3a18300500bd64f6f40) +--- + hw/usb/hcd-xhci.c | 44 +++++++++++++++++++++++++++++++++++++------- + 1 file changed, 37 insertions(+), 7 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 44 +++++++++++++++++++++++++++++++++++++------- + 1 files changed, 37 insertions(+), 7 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 55bcfc4..ccf7cc5 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -355,6 +355,7 @@ typedef struct XHCITransfer { + unsigned int streamid; + bool in_xfer; + bool iso_xfer; ++ bool timed_xfer; + + unsigned int trb_count; + unsigned int trb_alloced; +@@ -1787,6 +1788,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) + + xfer->in_xfer = bmRequestType & USB_DIR_IN; + xfer->iso_xfer = false; ++ xfer->timed_xfer = false; + + if (xhci_setup_packet(xfer) < 0) { + return -1; +@@ -1802,6 +1804,17 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer) + return 0; + } + ++static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer, ++ XHCIEPContext *epctx, uint64_t mfindex) ++{ ++ uint64_t asap = ((mfindex + epctx->interval - 1) & ++ ~(epctx->interval-1)); ++ uint64_t kick = epctx->mfindex_last + epctx->interval; ++ ++ assert(epctx->interval != 0); ++ xfer->mfindex_kick = MAX(asap, kick); ++} ++ + static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + XHCIEPContext *epctx, uint64_t mfindex) + { +@@ -1824,8 +1837,8 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer, + } + } + +-static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, +- XHCIEPContext *epctx, uint64_t mfindex) ++static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer, ++ XHCIEPContext *epctx, uint64_t mfindex) + { + if (xfer->mfindex_kick > mfindex) { + qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) + +@@ -1850,18 +1863,30 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx + switch(epctx->type) { + case ET_INTR_OUT: + case ET_INTR_IN: ++ xfer->pkts = 0; ++ xfer->iso_xfer = false; ++ xfer->timed_xfer = true; ++ mfindex = xhci_mfindex_get(xhci); ++ xhci_calc_intr_kick(xhci, xfer, epctx, mfindex); ++ xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); ++ if (xfer->running_retry) { ++ return -1; ++ } ++ break; + case ET_BULK_OUT: + case ET_BULK_IN: + xfer->pkts = 0; + xfer->iso_xfer = false; ++ xfer->timed_xfer = false; + break; + case ET_ISO_OUT: + case ET_ISO_IN: + xfer->pkts = 1; + xfer->iso_xfer = true; ++ xfer->timed_xfer = true; + mfindex = xhci_mfindex_get(xhci); + xhci_calc_iso_kick(xhci, xfer, epctx, mfindex); +- xhci_check_iso_kick(xhci, xfer, epctx, mfindex); ++ xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return -1; + } +@@ -1922,13 +1947,18 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, + + trace_usb_xhci_xfer_retry(xfer); + assert(xfer->running_retry); +- if (xfer->iso_xfer) { +- /* retry delayed iso transfer */ ++ if (xfer->timed_xfer) { ++ /* time to kick the transfer? */ + mfindex = xhci_mfindex_get(xhci); +- xhci_check_iso_kick(xhci, xfer, epctx, mfindex); ++ xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex); + if (xfer->running_retry) { + return; + } ++ xfer->timed_xfer = 0; ++ xfer->running_retry = 1; ++ } ++ if (xfer->iso_xfer) { ++ /* retry iso transfer */ + if (xhci_setup_packet(xfer) < 0) { + return; + } +@@ -2014,7 +2044,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, + epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE; + ep = xfer->packet.ep; + } else { +- if (!xfer->iso_xfer) { ++ if (!xfer->timed_xfer) { + fprintf(stderr, "xhci: error firing data transfer\n"); + } + } +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-fix-endpoint-interval-calculation.patch b/SOURCES/kvm-xhci-fix-endpoint-interval-calculation.patch new file mode 100644 index 0000000..5ad77a6 --- /dev/null +++ b/SOURCES/kvm-xhci-fix-endpoint-interval-calculation.patch @@ -0,0 +1,42 @@ +From 95fb890f69399c3c8bc59c1ae64851632247e804 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 12 Sep 2013 09:39:29 +0200 +Subject: [PATCH 01/25] xhci: fix endpoint interval calculation + +RH-Author: Gerd Hoffmann +Message-id: <1378978772-21612-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54338 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/4] xhci: fix endpoint interval calculation +Bugzilla: 1001604 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Hans de Goede +RH-Acked-by: Miroslav Rezanina + +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit ca7162782a293f525633e5816470498dd86a51cf) +--- + hw/usb/hcd-xhci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 233f3b6..55bcfc4 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -1241,7 +1241,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx, + epctx->ring.ccs = ctx[2] & 1; + } + +- epctx->interval = 1 << (ctx[0] >> 16) & 0xff; ++ epctx->interval = 1 << ((ctx[0] >> 16) & 0xff); + } + + static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-implement-warm-port-reset.patch b/SOURCES/kvm-xhci-implement-warm-port-reset.patch new file mode 100644 index 0000000..b5167d1 --- /dev/null +++ b/SOURCES/kvm-xhci-implement-warm-port-reset.patch @@ -0,0 +1,74 @@ +From 6e80e82c534ca31d46e556ab10b83ebbd381a627 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Fri, 30 Aug 2013 09:39:37 +0200 +Subject: [PATCH 08/29] xhci: implement warm port reset + +RH-Author: Gerd Hoffmann +Message-id: <1377855577-11693-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 53942 +O-Subject: [RHEL-7 qemu-kvm PATCH 1/1] xhci: implement warm port reset +Bugzilla: 949514 +RH-Acked-by: Hans de Goede +RH-Acked-by: Markus Armbruster +RH-Acked-by: Paolo Bonzini + +Without this patch windows can't do port resets for usb3 devices. + +https://bugzilla.redhat.com/show_bug.cgi?id=949514 + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit dad5b9ea0895c227bc9d48b7f0a6fa51eaaa8661) + +Note: the upstream commit message is incomplete. This patch also +fixes cold port reset with USB_SPEED_SUPER. +--- + hw/usb/hcd-xhci.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 13 +++++++++++-- + 1 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 3d3d6c3..233f3b6 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -2655,7 +2655,7 @@ static void xhci_port_update(XHCIPort *port, int is_detach) + xhci_port_notify(port, PORTSC_CSC); + } + +-static void xhci_port_reset(XHCIPort *port) ++static void xhci_port_reset(XHCIPort *port, bool warm_reset) + { + trace_usb_xhci_port_reset(port->portnr); + +@@ -2666,6 +2666,11 @@ static void xhci_port_reset(XHCIPort *port) + usb_device_reset(port->uport->dev); + + switch (port->uport->dev->speed) { ++ case USB_SPEED_SUPER: ++ if (warm_reset) { ++ port->portsc |= PORTSC_WRC; ++ } ++ /* fall through */ + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: +@@ -2828,8 +2833,12 @@ static void xhci_port_write(void *ptr, hwaddr reg, + switch (reg) { + case 0x00: /* PORTSC */ + /* write-1-to-start bits */ ++ if (val & PORTSC_WPR) { ++ xhci_port_reset(port, true); ++ break; ++ } + if (val & PORTSC_PR) { +- xhci_port_reset(port); ++ xhci_port_reset(port, false); + break; + } + +-- +1.7.1 + diff --git a/SOURCES/kvm-xhci-reset-port-when-disabling-slot.patch b/SOURCES/kvm-xhci-reset-port-when-disabling-slot.patch new file mode 100644 index 0000000..74eb083 --- /dev/null +++ b/SOURCES/kvm-xhci-reset-port-when-disabling-slot.patch @@ -0,0 +1,41 @@ +From 8aa4bf9e8049ab1f0f4beda2eaa620f970f98692 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 12 Sep 2013 09:39:31 +0200 +Subject: [PATCH 03/25] xhci: reset port when disabling slot + +RH-Author: Gerd Hoffmann +Message-id: <1378978772-21612-4-git-send-email-kraxel@redhat.com> +Patchwork-id: 54336 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/4] xhci: reset port when disabling slot +Bugzilla: 1001604 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Hans de Goede +RH-Acked-by: Miroslav Rezanina + +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 5c67dd7b4884979a2613a4702ac1ab68b0e6a16e) +--- + hw/usb/hcd-xhci.c | 1 + + 1 file changed, 1 insertion(+) + +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index ccf7cc5..0061cbe 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -2090,6 +2090,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid) + + xhci->slots[slotid-1].enabled = 0; + xhci->slots[slotid-1].addressed = 0; ++ xhci->slots[slotid-1].uport = NULL; + return CC_SUCCESS; + } + +-- +1.7.1 + diff --git a/SOURCES/misc-disable-s3-s4-by-default.patch b/SOURCES/misc-disable-s3-s4-by-default.patch new file mode 100644 index 0000000..ab28489 --- /dev/null +++ b/SOURCES/misc-disable-s3-s4-by-default.patch @@ -0,0 +1,50 @@ +From 9830eecd6989198882fa2c4ef132665f36ee7abe Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:06:56 +0200 +Subject: disable s3/s4 by default + +Message-id: <1374235471-27096-2-git-send-email-armbru@redhat.com> +Patchwork-id: 52604 +O-Subject: [RHEL-7 PATCH qemu-kvm 1/2] disable s3/s4 by default +Bugzilla: 980840 +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Gleb Natapov + +From: Gleb Natapov + +After the changes proposed in Bug 827503, S3/S4 will be enabled by +default on qemu/seabios, but we want it disabled by default in RHEL6.4 +to avoid problems on problematic OSes (it'll be enabled on a +case-by-case basis in the management layer). + +Since we want to have it fully supported when enabled, QE should perform +the expected tests (which AFAIK have been run in rhel6.3 already, so +enabling it manually should not be a problem). + +Signed-off-by: Gleb Natapov +Signed-off-by: Eduardo Habkost +(cherry picked from commit 625992f4673989108819db751aa9066b65fc6020) + +Picked from qemu-kvm-rhel6. + +Conflicts: + hw/acpi.c +Signed-off-by: Markus Armbruster + +diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c +index c4af1cc..86ff598 100644 +--- a/hw/acpi/piix4.c ++++ b/hw/acpi/piix4.c +@@ -475,8 +475,8 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, + + static Property piix4_pm_properties[] = { + DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), +- DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0), +- DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0), ++ DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 1), ++ DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 1), + DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2), + DEFINE_PROP_END_OF_LIST(), + }; diff --git a/SOURCES/pc-Add-machine-type-rhel6-0-0.patch b/SOURCES/pc-Add-machine-type-rhel6-0-0.patch new file mode 100644 index 0000000..a62e98a --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-0-0.patch @@ -0,0 +1,280 @@ +From 9010afecdea6872235b1692c4ee5f04cca2dbcf2 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:02:14 +0200 +Subject: pc: Add machine type "rhel6.0.0" + +Message-id: <1375201922-6794-3-git-send-email-armbru@redhat.com> +Patchwork-id: 52821 +O-Subject: [RHEL-7 PATCH v3 02/15] pc: Add machine type "rhel6.0.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Make it a copy of upstream's pc-0.12 type. Change name and desc. +Collect the scattered compat_props in one place (no functional +change). Copy the init function. + +The next few commits will morph compat_props and init function from +"same as upstream's pc-0.12" into "compatible with RHEL-6's +rhel6.0.0". + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 070a50d..bdb1b11 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,9 +777,252 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + ++#define PC_RHEL6_0_COMPAT \ ++ {\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "scsi-hd",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "scsi-cd",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "scsi-disk",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "ide-hd",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "ide-cd",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "ide-drive",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "virtio-blk-pci",\ ++ .property = "discard_granularity",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "virtio-serial-pci",\ ++ .property = "vectors",\ ++ /* DEV_NVECTORS_UNSPECIFIED as a uint32_t string */\ ++ .value = stringify(0xFFFFFFFF),\ ++ },{\ ++ .driver = "e1000",\ ++ .property = "romfile",\ ++ .value = "pxe-e1000.rom",\ ++ },{\ ++ .driver = "ne2k_pci",\ ++ .property = "romfile",\ ++ .value = "pxe-ne2k_pci.rom",\ ++ },{\ ++ .driver = "pcnet",\ ++ .property = "romfile",\ ++ .value = "pxe-pcnet.rom",\ ++ },{\ ++ .driver = "rtl8139",\ ++ .property = "romfile",\ ++ .value = "pxe-rtl8139.rom",\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "romfile",\ ++ .value = "pxe-virtio.rom",\ ++ },{\ ++ .driver = "486-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "usb-tablet",\ ++ .property = "usb_version",\ ++ .value = stringify(1),\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "ctrl_mac_addr",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "mq",\ ++ .value = "off",\ ++ },{\ ++ .driver = "e1000",\ ++ .property = "autonegotiation",\ ++ .value = "off",\ ++ },{\ ++ .driver = "nec-usb-xhci",\ ++ .property = "msi",\ ++ .value = "off",\ ++ },{\ ++ .driver = "nec-usb-xhci",\ ++ .property = "msix",\ ++ .value = "off",\ ++ },{\ ++ .driver = "ivshmem",\ ++ .property = "use64",\ ++ .value = "0",\ ++ },{\ ++ .driver = "qxl",\ ++ .property = "revision",\ ++ .value = stringify(3),\ ++ },{\ ++ .driver = "qxl-vga",\ ++ .property = "revision",\ ++ .value = stringify(3),\ ++ },{\ ++ .driver = "VGA",\ ++ .property = "mmio",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-scsi-pci",\ ++ .property = "hotplug",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-scsi-pci",\ ++ .property = "param_change",\ ++ .value = "off",\ ++ },{\ ++ .driver = "VGA",\ ++ .property = "vgamem_mb",\ ++ .value = stringify(8),\ ++ },{\ ++ .driver = "vmware-svga",\ ++ .property = "vgamem_mb",\ ++ .value = stringify(8),\ ++ },{\ ++ .driver = "qxl-vga",\ ++ .property = "vgamem_mb",\ ++ .value = stringify(8),\ ++ },{\ ++ .driver = "qxl",\ ++ .property = "vgamem_mb",\ ++ .value = stringify(8),\ ++ },{\ ++ .driver = "virtio-blk-pci",\ ++ .property = "config-wce",\ ++ .value = "off",\ ++ },{\ ++ .driver = "pc-sysfw",\ ++ .property = "rom_only",\ ++ .value = stringify(1),\ ++ },{\ ++ .driver = TYPE_ISA_FDC,\ ++ .property = "check_media_rate",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-balloon-pci",\ ++ .property = "class",\ ++ .value = stringify(PCI_CLASS_MEMORY_RAM),\ ++ },{\ ++ .driver = "apic",\ ++ .property = "vapic",\ ++ .value = "off",\ ++ },{\ ++ .driver = TYPE_USB_DEVICE,\ ++ .property = "full-path",\ ++ .value = "no",\ ++ },{\ ++ .driver = "virtio-blk-pci",\ ++ .property = "event_idx",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-serial-pci",\ ++ .property = "event_idx",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-net-pci",\ ++ .property = "event_idx",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-balloon-pci",\ ++ .property = "event_idx",\ ++ .value = "off",\ ++ },{\ ++ .driver = TYPE_PCI_DEVICE,\ ++ .property = "command_serr_enable",\ ++ .value = "off",\ ++ },{\ ++ .driver = "AC97",\ ++ .property = "use_broken_id",\ ++ .value = stringify(1),\ ++ },{\ ++ .driver = "virtio-serial-pci",\ ++ .property = "max_ports",\ ++ .value = stringify(1),\ ++ },{\ ++ .driver = "virtio-serial-pci",\ ++ .property = "vectors",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "VGA",\ ++ .property = "rombar",\ ++ .value = stringify(0),\ ++ },{\ ++ .driver = "vmware-svga",\ ++ .property = "rombar",\ ++ .value = stringify(0),\ ++ } ++ ++static void pc_init_rhel600(QEMUMachineInitArgs *args) ++{ ++ ram_addr_t ram_size = args->ram_size; ++ const char *cpu_model = args->cpu_model; ++ const char *kernel_filename = args->kernel_filename; ++ const char *kernel_cmdline = args->kernel_cmdline; ++ const char *initrd_filename = args->initrd_filename; ++ const char *boot_device = args->boot_device; ++ has_pvpanic = false; ++ disable_kvm_pv_eoi(); ++ enable_compat_apic_id_mode(); ++ pc_init1(get_system_memory(), ++ get_system_io(), ++ ram_size, boot_device, ++ kernel_filename, kernel_cmdline, ++ initrd_filename, cpu_model, 1, 0); ++} ++ ++static QEMUMachine pc_machine_rhel600 = { ++ .name = "rhel6.0.0", ++ .desc = "RHEL 6.0.0 PC", ++ .init = pc_init_rhel600, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_0_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel600); + } + + machine_init(rhel_machine_init); diff --git a/SOURCES/pc-Add-machine-type-rhel6-1-0.patch b/SOURCES/pc-Add-machine-type-rhel6-1-0.patch new file mode 100644 index 0000000..136c8b9 --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-1-0.patch @@ -0,0 +1,110 @@ +From 80dd2cb01a00e19e5227955e31fcfebbfcec1f85 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:04:57 +0200 +Subject: pc: Add machine type "rhel6.1.0" + +Message-id: <1375201922-6794-11-git-send-email-armbru@redhat.com> +Patchwork-id: 52822 +O-Subject: [RHEL-7 PATCH v3 10/15] pc: Add machine type "rhel6.1.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Match RHEL-6's compat_props qxl.revision, qxl-vga.revision, +VGA.rombar. + +RHEL-6's vmware-svga.rombar isn't needed, as we won't ship the device. + +RHEL-6's non-upstream virtio-serial-pci.flow_control isn't needed. +RHEL-6 has it to enable migration back to RHEL-6.0 (see qemu-kvm-rhel6 +commit 975ced4), which isn't relevant in RHEL-7. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index e48545b..4ab39cd 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,7 +777,7 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + +-#define PC_RHEL6_0_COMPAT \ ++#define PC_RHEL6_1_COMPAT \ + {\ + .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "model",\ +@@ -870,11 +870,11 @@ static QEMUMachine pc_machine_rhel700 = { + },{\ + .driver = "qxl",\ + .property = "revision",\ +- .value = stringify(1),\ ++ .value = stringify(2),\ + },{\ + .driver = "qxl-vga",\ + .property = "revision",\ +- .value = stringify(1),\ ++ .value = stringify(2),\ + },{\ + .driver = "VGA",\ + .property = "mmio",\ +@@ -923,6 +923,38 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "AC97",\ + .property = "use_broken_id",\ + .value = stringify(1),\ ++ } ++ ++static void pc_init_rhel610(QEMUMachineInitArgs *args) ++{ ++ has_pvpanic = false; ++ disable_kvm_pv_eoi(); ++ enable_compat_apic_id_mode(); ++ pc_init_rhel700(args); ++} ++ ++static QEMUMachine pc_machine_rhel610 = { ++ .name = "rhel6.1.0", ++ .desc = "RHEL 6.1.0 PC", ++ .init = pc_init_rhel610, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_1_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++#define PC_RHEL6_0_COMPAT \ ++ PC_RHEL6_1_COMPAT,\ ++ {\ ++ .driver = "qxl",\ ++ .property = "revision",\ ++ .value = stringify(1),\ ++ },{\ ++ .driver = "qxl-vga",\ ++ .property = "revision",\ ++ .value = stringify(1),\ + },{\ + .driver = "VGA",\ + .property = "rombar",\ +@@ -931,10 +963,7 @@ static QEMUMachine pc_machine_rhel700 = { + + static void pc_init_rhel600(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; +- disable_kvm_pv_eoi(); +- enable_compat_apic_id_mode(); +- pc_init_rhel700(args); ++ pc_init_rhel610(args); + } + + static QEMUMachine pc_machine_rhel600 = { +@@ -952,6 +981,7 @@ static QEMUMachine pc_machine_rhel600 = { + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel610); + qemu_register_machine(&pc_machine_rhel600); + } + diff --git a/SOURCES/pc-Add-machine-type-rhel6-2-0.patch b/SOURCES/pc-Add-machine-type-rhel6-2-0.patch new file mode 100644 index 0000000..29af189 --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-2-0.patch @@ -0,0 +1,137 @@ +From 26e8594d99236281d19435ba40c323665ca21bcd Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:05:31 +0200 +Subject: pc: Add machine type "rhel6.2.0" + +Message-id: <1375201922-6794-12-git-send-email-armbru@redhat.com> +Patchwork-id: 52823 +O-Subject: [RHEL-7 PATCH v3 11/15] pc: Add machine type "rhel6.2.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Match RHEL-6's compat_props qxl.revision, +qxl-vga.revision. virtio-blk-pci.event_idx, +virtio-serial-pci.event_idx, virtio-net-pci.event_idx, +virtio-balloon-pci.event_idx. + +RHEL-6's non-upstream hda-duplex.mcompat, hda-micro.mcompat, +hda-output.mcompat aren't needed. RHEL-6 has them to enable migration +back to RHEL-6.1 (see qemu-kvm-rhel6 commit d619762), which isn't +relevant in RHEL-7. + +Non-upstream usb-tablet.migrate, usb-mouse.migrate, usb-kbd.migrate +will be covered separately (bug 953304). + +PIIX4_PM.disable_s3, PIIX4_PM.disable_s4 will be covered separately +(bug 980840). + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 4ab39cd..eaf3af1 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,7 +777,7 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + +-#define PC_RHEL6_1_COMPAT \ ++#define PC_RHEL6_2_COMPAT \ + {\ + .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "model",\ +@@ -870,11 +870,11 @@ static QEMUMachine pc_machine_rhel700 = { + },{\ + .driver = "qxl",\ + .property = "revision",\ +- .value = stringify(2),\ ++ .value = stringify(3),\ + },{\ + .driver = "qxl-vga",\ + .property = "revision",\ +- .value = stringify(2),\ ++ .value = stringify(3),\ + },{\ + .driver = "VGA",\ + .property = "mmio",\ +@@ -900,6 +900,46 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "class",\ + .value = stringify(PCI_CLASS_MEMORY_RAM),\ + },{\ ++ .driver = TYPE_PCI_DEVICE,\ ++ .property = "command_serr_enable",\ ++ .value = "off",\ ++ },{\ ++ .driver = "AC97",\ ++ .property = "use_broken_id",\ ++ .value = stringify(1),\ ++ } ++ ++static void pc_init_rhel620(QEMUMachineInitArgs *args) ++{ ++ has_pvpanic = false; ++ disable_kvm_pv_eoi(); ++ enable_compat_apic_id_mode(); ++ pc_init_rhel700(args); ++} ++ ++static QEMUMachine pc_machine_rhel620 = { ++ .name = "rhel6.2.0", ++ .desc = "RHEL 6.2.0 PC", ++ .init = pc_init_rhel620, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_2_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++#define PC_RHEL6_1_COMPAT \ ++ PC_RHEL6_2_COMPAT,\ ++ {\ ++ .driver = "qxl",\ ++ .property = "revision",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "qxl-vga",\ ++ .property = "revision",\ ++ .value = stringify(2),\ ++ },{\ + .driver = "virtio-blk-pci",\ + .property = "event_idx",\ + .value = "off",\ +@@ -915,22 +955,11 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "virtio-balloon-pci",\ + .property = "event_idx",\ + .value = "off",\ +- },{\ +- .driver = TYPE_PCI_DEVICE,\ +- .property = "command_serr_enable",\ +- .value = "off",\ +- },{\ +- .driver = "AC97",\ +- .property = "use_broken_id",\ +- .value = stringify(1),\ + } + + static void pc_init_rhel610(QEMUMachineInitArgs *args) + { +- has_pvpanic = false; +- disable_kvm_pv_eoi(); +- enable_compat_apic_id_mode(); +- pc_init_rhel700(args); ++ pc_init_rhel620(args); + } + + static QEMUMachine pc_machine_rhel610 = { +@@ -981,6 +1010,7 @@ static QEMUMachine pc_machine_rhel600 = { + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel620); + qemu_register_machine(&pc_machine_rhel610); + qemu_register_machine(&pc_machine_rhel600); + } diff --git a/SOURCES/pc-Add-machine-type-rhel6-3-0.patch b/SOURCES/pc-Add-machine-type-rhel6-3-0.patch new file mode 100644 index 0000000..4dcbaa0 --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-3-0.patch @@ -0,0 +1,75 @@ +From 04ee5ae0197b004e2fb59970359da39788868182 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:05:46 +0200 +Subject: pc: Add machine type "rhel6.3.0" + +Message-id: <1375201922-6794-13-git-send-email-armbru@redhat.com> +Patchwork-id: 52826 +O-Subject: [RHEL-7 PATCH v3 12/15] pc: Add machine type "rhel6.3.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +RHEL-6's non-upstream virtio-net-pci.x-__com_redhat_rhel620_compat +will be covered separately, if necessary (no BZ yet). + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index eaf3af1..dff2543 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,7 +777,7 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + +-#define PC_RHEL6_2_COMPAT \ ++#define PC_RHEL6_3_COMPAT \ + {\ + .driver = "Conroe-" TYPE_X86_CPU,\ + .property = "model",\ +@@ -909,7 +909,7 @@ static QEMUMachine pc_machine_rhel700 = { + .value = stringify(1),\ + } + +-static void pc_init_rhel620(QEMUMachineInitArgs *args) ++static void pc_init_rhel630(QEMUMachineInitArgs *args) + { + has_pvpanic = false; + disable_kvm_pv_eoi(); +@@ -917,6 +917,26 @@ static void pc_init_rhel620(QEMUMachineInitArgs *args) + pc_init_rhel700(args); + } + ++static QEMUMachine pc_machine_rhel630 = { ++ .name = "rhel6.3.0", ++ .desc = "RHEL 6.3.0 PC", ++ .init = pc_init_rhel630, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_3_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++#define PC_RHEL6_2_COMPAT \ ++ PC_RHEL6_3_COMPAT ++ ++static void pc_init_rhel620(QEMUMachineInitArgs *args) ++{ ++ pc_init_rhel630(args); ++} ++ + static QEMUMachine pc_machine_rhel620 = { + .name = "rhel6.2.0", + .desc = "RHEL 6.2.0 PC", +@@ -1010,6 +1030,7 @@ static QEMUMachine pc_machine_rhel600 = { + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel630); + qemu_register_machine(&pc_machine_rhel620); + qemu_register_machine(&pc_machine_rhel610); + qemu_register_machine(&pc_machine_rhel600); diff --git a/SOURCES/pc-Add-machine-type-rhel6-4-0.patch b/SOURCES/pc-Add-machine-type-rhel6-4-0.patch new file mode 100644 index 0000000..f94bd25 --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-4-0.patch @@ -0,0 +1,208 @@ +From fce3651ee99dd18501b9302d72cd8c0af098a235 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:05:58 +0200 +Subject: pc: Add machine type "rhel6.4.0" + +Message-id: <1375201922-6794-14-git-send-email-armbru@redhat.com> +Patchwork-id: 52820 +O-Subject: [RHEL-7 PATCH v3 13/15] pc: Add machine type "rhel6.4.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Match RHEL-6's set_cpu_model_level() by equivalent compat_props model +and level. + +Match RHEL-6's compat_props qxl.revision, qxl-vga.revision, +virtio-scsi-pci.hotplug, virtio-scsi-pci.param_change. + +RHEL-6's non-upstream USB.create_unique_serial will be covered +separately (either bug 953304 or a new one). + +RHEL-6's non-upstream isa-fdc.migrate_dir isn't needed. RHEL-6 has it +to enable migration back to RHEL-6.3 (see qemu-kvm-rhel6 commit +a214015), which isn't relevant in RHEL-7. + +Match RHEL-6's non-upstream e1000.x-__com_redhat_rhel630_compat by +upstream's e1000.autonegotiation, as follows. + +Upstream commit 2af234e disables auto-negotiation for older machine +types, by defining property e1000.autonegotiation and putting it into +suitable compat_props. The corresponding RHEL-6 commit da4452c does +not add this property. Instead, it reuses +e1000.x-__com_redhat_rhel630_compat, with the sense reverted. This +turns autonegotiation off for rhel6.3.0 and older. + +RHEL-7 inherits the upstream solution. We need to set +e1000.autonegotiation for exactly the machine types where +e1000.x-__com_redhat_rhel630_compat is on in RHEL-6, namely rhel6.3.0 +and older. + +Match RHEL-6's disable_kvm_pv_eoi(). + +Match RHEL-6's compat_contiguous_apic_ids by upstream's +enable_compat_apic_id_mode(). + +RHEL-6's set_pmu_passthrough() and disable_tsc_deadline() will be +covered separately (bug 918907). + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index dff2543..a922645 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,32 +777,8 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + +-#define PC_RHEL6_3_COMPAT \ ++#define PC_RHEL6_4_COMPAT \ + {\ +- .driver = "Conroe-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Conroe-" TYPE_X86_CPU,\ +- .property = "level",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Penryn-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Penryn-" TYPE_X86_CPU,\ +- .property = "level",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Nehalem-" TYPE_X86_CPU,\ +- .property = "model",\ +- .value = stringify(2),\ +- },{\ +- .driver = "Nehalem-" TYPE_X86_CPU,\ +- .property = "level",\ +- .value = stringify(2),\ +- },{\ + .driver = "scsi-hd",\ + .property = "discard_granularity",\ + .value = stringify(0),\ +@@ -864,30 +840,10 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "mq",\ + .value = "off",\ + },{\ +- .driver = "e1000",\ +- .property = "autonegotiation",\ +- .value = "off",\ +- },{\ +- .driver = "qxl",\ +- .property = "revision",\ +- .value = stringify(3),\ +- },{\ +- .driver = "qxl-vga",\ +- .property = "revision",\ +- .value = stringify(3),\ +- },{\ + .driver = "VGA",\ + .property = "mmio",\ + .value = "off",\ + },{\ +- .driver = "virtio-scsi-pci",\ +- .property = "hotplug",\ +- .value = "off",\ +- },{\ +- .driver = "virtio-scsi-pci",\ +- .property = "param_change",\ +- .value = "off",\ +- },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ +@@ -909,12 +865,77 @@ static QEMUMachine pc_machine_rhel700 = { + .value = stringify(1),\ + } + +-static void pc_init_rhel630(QEMUMachineInitArgs *args) ++static void pc_init_rhel640(QEMUMachineInitArgs *args) + { + has_pvpanic = false; ++ pc_init_rhel700(args); ++} ++ ++static QEMUMachine pc_machine_rhel640 = { ++ .name = "rhel6.4.0", ++ .desc = "RHEL 6.4.0 PC", ++ .init = pc_init_rhel640, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_4_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++#define PC_RHEL6_3_COMPAT \ ++ PC_RHEL6_4_COMPAT,\ ++ {\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "e1000",\ ++ .property = "autonegotiation",\ ++ .value = "off",\ ++ },{\ ++ .driver = "qxl",\ ++ .property = "revision",\ ++ .value = stringify(3),\ ++ },{\ ++ .driver = "qxl-vga",\ ++ .property = "revision",\ ++ .value = stringify(3),\ ++ },{\ ++ .driver = "virtio-scsi-pci",\ ++ .property = "hotplug",\ ++ .value = "off",\ ++ },{\ ++ .driver = "virtio-scsi-pci",\ ++ .property = "param_change",\ ++ .value = "off",\ ++ } ++ ++static void pc_init_rhel630(QEMUMachineInitArgs *args) ++{ + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- pc_init_rhel700(args); ++ pc_init_rhel640(args); + } + + static QEMUMachine pc_machine_rhel630 = { +@@ -1030,6 +1051,7 @@ static QEMUMachine pc_machine_rhel600 = { + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel640); + qemu_register_machine(&pc_machine_rhel630); + qemu_register_machine(&pc_machine_rhel620); + qemu_register_machine(&pc_machine_rhel610); diff --git a/SOURCES/pc-Add-machine-type-rhel6-5-0.patch b/SOURCES/pc-Add-machine-type-rhel6-5-0.patch new file mode 100644 index 0000000..2192230 --- /dev/null +++ b/SOURCES/pc-Add-machine-type-rhel6-5-0.patch @@ -0,0 +1,83 @@ +From 8f9887acd04e8db0bebd0ad3fe1cf5d7294abdfd Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:06:25 +0200 +Subject: pc: Add machine type "rhel6.5.0" + +Message-id: <1375201922-6794-15-git-send-email-armbru@redhat.com> +Patchwork-id: 52824 +O-Subject: [RHEL-7 PATCH v3 14/15] pc: Add machine type "rhel6.5.0" +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Match RHEL-6's virtio-scsi-pci.vectors. Note: upstream commit 4c205d0 +"virtio-scsi: enable MSI-X support" changed vectors from 2 to +DEV_NVECTORS_UNSPECIFIED. The necessary compat_props to keep it at 2 +for old machine types were forgotten. The RHEL-6 backport (commit +0ef7672) added them. + +Match RHEL-6's has_pvpanic. + +RHEL-6's disable_kvm_sep() will be covered separately (bug 918907). + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index a922645..5ca2cc3 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -777,7 +777,7 @@ static QEMUMachine pc_machine_rhel700 = { + DEFAULT_MACHINE_OPTIONS, + }; + +-#define PC_RHEL6_4_COMPAT \ ++#define PC_RHEL6_5_COMPAT \ + {\ + .driver = "scsi-hd",\ + .property = "discard_granularity",\ +@@ -865,10 +865,35 @@ static QEMUMachine pc_machine_rhel700 = { + .value = stringify(1),\ + } + ++static void pc_init_rhel650(QEMUMachineInitArgs *args) ++{ ++ pc_init_rhel700(args); ++} ++ ++static QEMUMachine pc_machine_rhel650 = { ++ .name = "rhel6.5.0", ++ .desc = "RHEL 6.5.0 PC", ++ .init = pc_init_rhel650, ++ .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_RHEL6_5_COMPAT, ++ { /* end of list */ } ++ }, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++#define PC_RHEL6_4_COMPAT \ ++ PC_RHEL6_5_COMPAT,\ ++ {\ ++ .driver = "virtio-scsi-pci",\ ++ .property = "vectors",\ ++ .value = stringify(2),\ ++ } ++ + static void pc_init_rhel640(QEMUMachineInitArgs *args) + { + has_pvpanic = false; +- pc_init_rhel700(args); ++ pc_init_rhel650(args); + } + + static QEMUMachine pc_machine_rhel640 = { +@@ -1051,6 +1076,7 @@ static QEMUMachine pc_machine_rhel600 = { + static void rhel_machine_init(void) + { + qemu_register_machine(&pc_machine_rhel700); ++ qemu_register_machine(&pc_machine_rhel650); + qemu_register_machine(&pc_machine_rhel640); + qemu_register_machine(&pc_machine_rhel630); + qemu_register_machine(&pc_machine_rhel620); diff --git a/SOURCES/pc-Disable-the-use-flash-device-for-BIOS-unless-KVM-misfeature.patch b/SOURCES/pc-Disable-the-use-flash-device-for-BIOS-unless-KVM-misfeature.patch new file mode 100644 index 0000000..d8f806c --- /dev/null +++ b/SOURCES/pc-Disable-the-use-flash-device-for-BIOS-unless-KVM-misfeature.patch @@ -0,0 +1,97 @@ +From 62868855d0fdd34dee119a59c7e56c1706fc27ab Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:00:55 +0200 +Subject: pc: Disable the "use flash device for BIOS unless KVM" misfeature + +Message-id: <1373453682-19227-2-git-send-email-armbru@redhat.com> +Patchwork-id: 52417 +O-Subject: [RHEL-7 PATCH qemu-kvm 1/1] pc: Disable the "use flash device for BIOS unless KVM" misfeature +Bugzilla: 963280 +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini + +Use of a flash memory device for the BIOS was added in series "[PATCH +v10 0/8] PC system flash support", commit 4732dca..1b89faf, v1.1. + +Flash vs. ROM is a guest-visible difference. Thus, flash use had to +be suppressed for machine types pc-1.0 and older. This was +accomplished by adding a dummy device "pc-sysfw" with property +"rom_only": + +* Non-zero rom_only means "use ROM". Default for pc-1.0 and older. +* Zero rom_only means "maybe use flash". Default for newer machines. + +Not only is the dummy device ugly, it was also retroactively added to +the older machine types! Fortunately, it's not guest-visible (thus no +immediate guest ABI breakage), and has no vmstate (thus no immediate +migration breakage). Breakage occurs only if the user unwisely +enables flash by setting rom_only to zero. Patch review FAIL #1. + +Why "maybe use flash"? Flash didn't work with KVM. Therefore, +rom_only=0 really means "use flash, except when KVM is enabled, use +ROM". This is a Bad Idea, because it makes enabling/ disabling KVM +guest-visible. Patch review FAIL #2. + +Aside: it also precludes migrating between KVM on and off, but that's +not possible for other reasons anyway. + +Upstream commit 9953f88 killed the misfeature for new machine types. +Upstream commit 9e1c2ec reverted the kill, but left a dead variable +behind. This is what's in RHEL-7 is before this patch. + +KVM has recently been made to support flash (KVM_CAP_READONLY_MEM), +which permitted upstream QEMU to redo the flash vs. ROM switch +properly (commit 338ea90..dafb82e). The required follow-up cleanup +hasn't been committed, yet: Paolo's [PATCH v2 0/3] Remove legacy sysfw +code. + +Instead of backporting all that, I'm simply ripping out the flash +feature. ROM has been working just fine for us, and I don't think we +should complicate RHEL-7 maintenance and support by having two ways to +map BIOS, at least not without sufficient business reason. + +The result behaves just like upstream with the follow-up cleanup +applied, except -pflash doesn't affect the BIOS mapping, but remains +as it always was: it creates an unused drive. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c +index 4f17668..2bbedc9 100644 +--- a/hw/block/pc_sysfw.c ++++ b/hw/block/pc_sysfw.c +@@ -36,6 +36,7 @@ + + #define BIOS_FILENAME "bios.bin" + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + typedef struct PcSysFwDevice { + SysBusDevice busdev; + uint8_t rom_only; +@@ -138,6 +139,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory, + + pc_isa_bios_init(rom_memory, flash_mem, size); + } ++#endif /* Disabled for Red Hat Enterprise Linux */ + + static void old_pc_system_rom_init(MemoryRegion *rom_memory) + { +@@ -194,6 +196,7 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory) + bios); + } + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ + /* + * Bug-compatible flash vs. ROM selection enabled? + * A few older machines enable this. +@@ -287,3 +290,9 @@ static void pcsysfw_register (void) + + type_init (pcsysfw_register); + ++#else /* Disabled for Red Hat Enterprise Linux */ ++void pc_system_firmware_init(MemoryRegion *rom_memory) ++{ ++ old_pc_system_rom_init(rom_memory); ++} ++#endif diff --git a/SOURCES/pc-Drop-RHEL-6-USB-device-compat_prop-full-path.patch b/SOURCES/pc-Drop-RHEL-6-USB-device-compat_prop-full-path.patch new file mode 100644 index 0000000..2e11a4f --- /dev/null +++ b/SOURCES/pc-Drop-RHEL-6-USB-device-compat_prop-full-path.patch @@ -0,0 +1,36 @@ +From ff0ad2681b06e4e7e0eadc281d3efda171bd1f5e Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:03:35 +0200 +Subject: pc: Drop RHEL-6 USB device compat_prop full-path + +Message-id: <1375201922-6794-6-git-send-email-armbru@redhat.com> +Patchwork-id: 52814 +O-Subject: [RHEL-7 PATCH v3 05/15] pc: Drop RHEL-6 USB device compat_prop full-path +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Upstream added property full-path to USB devices in commit eeb0cf9 +(v1.1) for migration compatibility. RHEL-6 got the feature in commit +29b10d1 (6.2), but without the property, because 6.2 was the first +version capable of migrating USB devices. Therefore, full-path needs +to remain on by default for all machine types. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 5d57a76..aae891e 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -904,10 +904,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "vapic",\ + .value = "off",\ + },{\ +- .driver = TYPE_USB_DEVICE,\ +- .property = "full-path",\ +- .value = "no",\ +- },{\ + .driver = "virtio-blk-pci",\ + .property = "event_idx",\ + .value = "off",\ diff --git a/SOURCES/pc-Drop-RHEL-6-compat_props-apic-kvm-apic-vapic.patch b/SOURCES/pc-Drop-RHEL-6-compat_props-apic-kvm-apic-vapic.patch new file mode 100644 index 0000000..3d36aba --- /dev/null +++ b/SOURCES/pc-Drop-RHEL-6-compat_props-apic-kvm-apic-vapic.patch @@ -0,0 +1,44 @@ +From 196b2691b4d55361527b887ec7bc044d423b7757 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:04:01 +0200 +Subject: pc: Drop RHEL-6 compat_props {apic, kvm-apic}.vapic + +Message-id: <1375201922-6794-8-git-send-email-armbru@redhat.com> +Patchwork-id: 52816 +O-Subject: [RHEL-7 PATCH v3 07/15] pc: Drop RHEL-6 compat_props {apic, kvm-apic}.vapic +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +RHEL-6's kvm_arch_create() calls kvm_tpr_opt_setup() #ifdef +KVM_EXIT_TPR_ACCESS, which is defined in RHEL-6. Adds migration +section "kvm-tpr-opt" when KVM is enabled. Comes from qemu-kvm, +initial commit 885e90b. + +It went into upstream qemu v1.1.0, but in different form (commit +e5ad936 "kvmvapic: Introduce TPR access optimization for Windows +guests"). Here, migration section "kvm-tpr-opt" belongs to qdev +"kvmvapic", which is created when the property kvm-apic.vapic +(inherited from apic_common) is on. Commit 9bea6a2 disables it for +older machine types, with suitable compat_props. + +Drop them from the RHEL-6 machine types. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 5dffeb2..9e96b79 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -900,10 +900,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "class",\ + .value = stringify(PCI_CLASS_MEMORY_RAM),\ + },{\ +- .driver = "apic",\ +- .property = "vapic",\ +- .value = "off",\ +- },{\ + .driver = "virtio-blk-pci",\ + .property = "event_idx",\ + .value = "off",\ diff --git a/SOURCES/pc-Drop-RHEL-6-compat_props-virtio-serial-pci-max_ports-vectors.patch b/SOURCES/pc-Drop-RHEL-6-compat_props-virtio-serial-pci-max_ports-vectors.patch new file mode 100644 index 0000000..19dea35 --- /dev/null +++ b/SOURCES/pc-Drop-RHEL-6-compat_props-virtio-serial-pci-max_ports-vectors.patch @@ -0,0 +1,37 @@ +From fc8a3e5647791e0e4fbcc28bb1e9afa5c158711f Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:03:48 +0200 +Subject: pc: Drop RHEL-6 compat_props virtio-serial-pci.{max_ports, vectors} + +Message-id: <1375201922-6794-7-git-send-email-armbru@redhat.com> +Patchwork-id: 52819 +O-Subject: [RHEL-7 PATCH v3 06/15] pc: Drop RHEL-6 compat_props virtio-serial-pci.{max_ports, vectors} +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +RHEL-6 has them only in RHEL-5 machine types. See qemu-kvm-rhel6 +commit aad5614. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index aae891e..5dffeb2 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -928,14 +928,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "use_broken_id",\ + .value = stringify(1),\ + },{\ +- .driver = "virtio-serial-pci",\ +- .property = "max_ports",\ +- .value = stringify(1),\ +- },{\ +- .driver = "virtio-serial-pci",\ +- .property = "vectors",\ +- .value = stringify(0),\ +- },{\ + .driver = "VGA",\ + .property = "rombar",\ + .value = stringify(0),\ diff --git a/SOURCES/pc-Drop-superfluous-RHEL-6-compat_props.patch b/SOURCES/pc-Drop-superfluous-RHEL-6-compat_props.patch new file mode 100644 index 0000000..1438bc1 --- /dev/null +++ b/SOURCES/pc-Drop-superfluous-RHEL-6-compat_props.patch @@ -0,0 +1,96 @@ +From 5e40d1551af04499f6e0f408e07dc5046123c6c0 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:02:36 +0200 +Subject: pc: Drop superfluous RHEL-6 compat_props + +Message-id: <1375201922-6794-4-git-send-email-armbru@redhat.com> +Patchwork-id: 52812 +O-Subject: [RHEL-7 PATCH v3 03/15] pc: Drop superfluous RHEL-6 compat_props +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Drop compatibility properties of + +* devices we won't ship: ne2k_pci, pcnet, pc-sysfw, vmware-svga + +* devices that are new in RHEL-7: nec-usb-xhci, ivshmem + +Re ivshmem: actually, the current plan is not to ship it (bug 787463). +Executing the plan will only flip the reason for dropping its +compatibility property, so no code conflict here. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index bdb1b11..96f6bf9 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -840,14 +840,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "romfile",\ + .value = "pxe-e1000.rom",\ + },{\ +- .driver = "ne2k_pci",\ +- .property = "romfile",\ +- .value = "pxe-ne2k_pci.rom",\ +- },{\ +- .driver = "pcnet",\ +- .property = "romfile",\ +- .value = "pxe-pcnet.rom",\ +- },{\ + .driver = "rtl8139",\ + .property = "romfile",\ + .value = "pxe-rtl8139.rom",\ +@@ -876,18 +868,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "autonegotiation",\ + .value = "off",\ + },{\ +- .driver = "nec-usb-xhci",\ +- .property = "msi",\ +- .value = "off",\ +- },{\ +- .driver = "nec-usb-xhci",\ +- .property = "msix",\ +- .value = "off",\ +- },{\ +- .driver = "ivshmem",\ +- .property = "use64",\ +- .value = "0",\ +- },{\ + .driver = "qxl",\ + .property = "revision",\ + .value = stringify(3),\ +@@ -912,10 +892,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "vgamem_mb",\ + .value = stringify(8),\ + },{\ +- .driver = "vmware-svga",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ + .driver = "qxl-vga",\ + .property = "vgamem_mb",\ + .value = stringify(8),\ +@@ -928,10 +904,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "config-wce",\ + .value = "off",\ + },{\ +- .driver = "pc-sysfw",\ +- .property = "rom_only",\ +- .value = stringify(1),\ +- },{\ + .driver = TYPE_ISA_FDC,\ + .property = "check_media_rate",\ + .value = "off",\ +@@ -983,10 +955,6 @@ static QEMUMachine pc_machine_rhel700 = { + .driver = "VGA",\ + .property = "rombar",\ + .value = stringify(0),\ +- },{\ +- .driver = "vmware-svga",\ +- .property = "rombar",\ +- .value = stringify(0),\ + } + + static void pc_init_rhel600(QEMUMachineInitArgs *args) diff --git a/SOURCES/pc-Give-rhel6-0-0-a-kvmclock.patch b/SOURCES/pc-Give-rhel6-0-0-a-kvmclock.patch new file mode 100644 index 0000000..5e293a9 --- /dev/null +++ b/SOURCES/pc-Give-rhel6-0-0-a-kvmclock.patch @@ -0,0 +1,51 @@ +From 9eb0daf6079beade2bcc13d0062d90a7644685f5 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:04:35 +0200 +Subject: pc: Give rhel6.0.0 a kvmclock + +Message-id: <1375201922-6794-10-git-send-email-armbru@redhat.com> +Patchwork-id: 52817 +O-Subject: [RHEL-7 PATCH v3 09/15] pc: Give rhel6.0.0 a kvmclock +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +RHEL-6.0 inherited kvmclock from upstream qemu-kvm. It later made its +way into upstream qemu (commit 0ec329d), and we switched to it in +RHEL-6.2 (commit 17ca2d2). + +Since kvmclock was new in upstream qemu, the commit took care to +enable it only for new machine types. Since it wasn't new in RHEL-6, +the backport dropped that part. + +Drop it in RHEL-7, too. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 57877e3..e48545b 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -931,20 +931,10 @@ static QEMUMachine pc_machine_rhel700 = { + + static void pc_init_rhel600(QEMUMachineInitArgs *args) + { +- ram_addr_t ram_size = args->ram_size; +- const char *cpu_model = args->cpu_model; +- const char *kernel_filename = args->kernel_filename; +- const char *kernel_cmdline = args->kernel_cmdline; +- const char *initrd_filename = args->initrd_filename; +- const char *boot_device = args->boot_device; + has_pvpanic = false; + disable_kvm_pv_eoi(); + enable_compat_apic_id_mode(); +- pc_init1(get_system_memory(), +- get_system_io(), +- ram_size, boot_device, +- kernel_filename, kernel_cmdline, +- initrd_filename, cpu_model, 1, 0); ++ pc_init_rhel700(args); + } + + static QEMUMachine pc_machine_rhel600 = { diff --git a/SOURCES/pc-replace-upstream-machine-types-by-rhel7-types.patch b/SOURCES/pc-replace-upstream-machine-types-by-rhel7-types.patch new file mode 100644 index 0000000..aa862b9 --- /dev/null +++ b/SOURCES/pc-replace-upstream-machine-types-by-rhel7-types.patch @@ -0,0 +1,120 @@ +commit ffacd352a92751dab005eaa1892676a91e788a10 +Author: Eduardo Habkost +Date: Thu Jun 27 15:57:41 2013 +0200 + + pc: Replace upstream machine types by RHEL-7 types + + RH-Author: Eduardo Habkost + Message-id: <1372348663-1706-2-git-send-email-ehabkost@redhat.com> + Patchwork-id: 52251 + O-Subject: [PATCH v2 1/3] pc: Replace upstream machine types by RHEL-7 types + Bugzilla: 977864 + RH-Acked-by: Bandan Das + RH-Acked-by: Markus Armbruster + RH-Acked-by: Paolo Bonzini + + From: Markus Armbruster + + Bugzilla: 977864 + Upstream status: not applicable + + Existing machine-types are commented-out instead of being deleted, to + help avoid backport conflicts in the future. + + Signed-off-by: Markus Armbruster + [ehabkost: edited patch description] + Signed-off-by: Eduardo Habkost + --- + hw/i386/pc_piix.c | 29 +++++++++++++++++++++++++++++ + hw/i386/pc_q35.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 57 insertions(+) + + Signed-off-by: Miroslav Rezanina + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index e26c93d..d8d74a3 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -246,6 +246,8 @@ static void pc_init_pci(QEMUMachineInitArgs *args) + initrd_filename, cpu_model, 1, 1); + } + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ ++ + static void pc_init_pci_1_4(QEMUMachineInitArgs *args) + { + has_pvpanic = false; +@@ -778,3 +780,30 @@ static void pc_machine_init(void) + } + + machine_init(pc_machine_init); ++ ++#endif /* Disabled for Red Hat Enterprise Linux */ ++ ++/* Red Hat Enterprise Linux machine types */ ++ ++static void pc_init_rhel700(QEMUMachineInitArgs *args) ++{ ++ pc_init_pci(args); ++} ++ ++static QEMUMachine pc_machine_rhel700 = { ++ .name = "pc-i440fx-rhel7.0.0", ++ .alias = "pc", ++ .desc = "RHEL 7.0.0 PC (i440FX + PIIX, 1996)", ++ .init = pc_init_rhel700, ++ .hot_add_cpu = pc_hot_add_cpu, ++ .max_cpus = 255, ++ .is_default = 1, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++static void rhel_machine_init(void) ++{ ++ qemu_register_machine(&pc_machine_rhel700); ++} ++ ++machine_init(rhel_machine_init); +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 7888dfe..9bcad00 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -208,6 +208,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args) + } + } + ++#if 0 /* Disabled for Red Hat Enterprise Linux */ ++ + static void pc_q35_init_1_4(QEMUMachineInitArgs *args) + { + has_pvpanic = false; +@@ -244,3 +246,29 @@ static void pc_q35_machine_init(void) + } + + machine_init(pc_q35_machine_init); ++ ++#endif /* Disabled for Red Hat Enterprise Linux */ ++ ++/* Red Hat Enterprise Linux machine types */ ++ ++static void pc_q35_init_rhel700(QEMUMachineInitArgs *args) ++{ ++ pc_q35_init(args); ++} ++ ++static QEMUMachine pc_q35_machine_rhel700 = { ++ .name = "pc-q35-rhel7.0.0", ++ .alias = "q35", ++ .desc = "RHEL-7.0.0 PC (Q35 + ICH9, 2009)", ++ .init = pc_q35_init_rhel700, ++ .hot_add_cpu = pc_hot_add_cpu, ++ .max_cpus = 255, ++ DEFAULT_MACHINE_OPTIONS, ++}; ++ ++static void rhel_pc_q35_machine_init(void) ++{ ++ qemu_register_machine(&pc_q35_machine_rhel700); ++} ++ ++machine_init(rhel_pc_q35_machine_init); diff --git a/SOURCES/pc-rhel6-compat-enable-S3-S4-for-6-1-and-lower-machine-types.patch b/SOURCES/pc-rhel6-compat-enable-S3-S4-for-6-1-and-lower-machine-types.patch new file mode 100644 index 0000000..67bb9bb --- /dev/null +++ b/SOURCES/pc-rhel6-compat-enable-S3-S4-for-6-1-and-lower-machine-types.patch @@ -0,0 +1,67 @@ +From 66543c63c5be389816ab45cdc6eed93094345281 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:07:32 +0200 +Subject: pc: rhel6-compat: enable S3, S4 for 6.1 and lower machine types + +Message-id: <1374235471-27096-3-git-send-email-armbru@redhat.com> +Patchwork-id: 52605 +O-Subject: [RHEL-7 PATCH qemu-kvm 2/2] pc: rhel6-compat: enable S3, S4 for 6.1 and lower machine types +Bugzilla: 980840 +RH-Acked-by: Amit Shah +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Gleb Natapov + +From: Amit Shah + +We don't advertise S3/S4 support by default since RHEL6.2: + +RHEL6.4 has S3/S4 advertisement disabled by default (can be overriden by + the disable_s3 and disable_s4 properties of the PIIX4). +RHEL6.3 and 6.2 had S3/S4 advertisement disabled by default (can be + overriden by using the alternative bios-pm.bin SeaBIOS image). +RHEL6.1 and 6.0 had S3/S4 advertisement enabled by default. + +We need to ensure we keep that behaviour, so adjust the 6.1 and 6.0 +machine types to allow S3/S4. + +As a side note, migrating a RHEL6.0 or RHEL6.1 VM to a RHEL6.2 or 6.3 +host would have caused a guest-visible change, but we can do better +starting with 6.4, so let's do the right thing now. This, however, has +the potential to cause two guest-visible changes if a VM is migrated +like this: + +RHEL6.1 host --1--> RHEL6.3 host --2--> RHEL6.4 host + +After (1) above, guest will stop seeing S3/S4 advertised. After (2), +S3/S4 will be advertised again. + +Signed-off-by: Amit Shah +Signed-off-by: Michal Novotny +(cherry picked from commit ffc7768db990f0587b84e08e06095ed26f095fde) + +Picked from qemu-kvm-rhel6. + +Conflicts: + hw/pc.c +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 5ca2cc3..23002ce 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -998,6 +998,14 @@ static QEMUMachine pc_machine_rhel620 = { + #define PC_RHEL6_1_COMPAT \ + PC_RHEL6_2_COMPAT,\ + {\ ++ .driver = "PIIX4_PM",\ ++ .property = "disable_s3",\ ++ .value = "0",\ ++ },{\ ++ .driver = "PIIX4_PM",\ ++ .property = "disable_s4",\ ++ .value = "0",\ ++ },{\ + .driver = "qxl",\ + .property = "revision",\ + .value = stringify(2),\ diff --git a/SOURCES/qemu-ga.sysconfig b/SOURCES/qemu-ga.sysconfig new file mode 100644 index 0000000..f54018e --- /dev/null +++ b/SOURCES/qemu-ga.sysconfig @@ -0,0 +1,19 @@ +# This is a systemd environment file, not a shell script. +# It provides settings for "/lib/systemd/system/qemu-guest-agent.service". + +# Comma-separated blacklist of RPCs to disable, or empty list to enable all. +# +# You can get the list of RPC commands using "qemu-ga --blacklist='?'". +# There should be no spaces between commas and commands in the blacklist. +BLACKLIST_RPC=guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush + +# Fsfreeze hook script specification. +# +# FSFREEZE_HOOK_PATHNAME=/dev/null : disables the feature. +# +# FSFREEZE_HOOK_PATHNAME=/path/to/executable : enables the feature with the +# specified binary or shell script. +# +# FSFREEZE_HOOK_PATHNAME= : enables the feature with the +# default value (invoke "qemu-ga --help" to interrogate). +FSFREEZE_HOOK_PATHNAME=/etc/qemu-ga/fsfreeze-hook diff --git a/SOURCES/qemu-guest-agent.service b/SOURCES/qemu-guest-agent.service new file mode 100644 index 0000000..44b11cd --- /dev/null +++ b/SOURCES/qemu-guest-agent.service @@ -0,0 +1,18 @@ +[Unit] +Description=QEMU Guest Agent +BindsTo=dev-virtio\x2dports-org.qemu.guest_agent.0.device +After=dev-virtio\x2dports-org.qemu.guest_agent.0.device + +[Service] +UMask=0077 +EnvironmentFile=/etc/sysconfig/qemu-ga +ExecStart=/usr/bin/qemu-ga \ + --method=virtio-serial \ + --path=/dev/virtio-ports/org.qemu.guest_agent.0 \ + --blacklist=${BLACKLIST_RPC} \ + -F${FSFREEZE_HOOK_PATHNAME} +StandardError=syslog +Restart=always +RestartSec=0 + +[Install] diff --git a/SOURCES/qemu-kvm-Fix-migration-from-older-version-due-to-i8254-changes.patch b/SOURCES/qemu-kvm-Fix-migration-from-older-version-due-to-i8254-changes.patch new file mode 100644 index 0000000..4fa44e6 --- /dev/null +++ b/SOURCES/qemu-kvm-Fix-migration-from-older-version-due-to-i8254-changes.patch @@ -0,0 +1,64 @@ +From c9b5ec980523f458cf0e4cfd9f9d014e853f15aa Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:01:44 +0200 +Subject: qemu-kvm: Fix migration from older version due to i8254 changes + +Message-id: <1375201922-6794-2-git-send-email-armbru@redhat.com> +Patchwork-id: 52815 +O-Subject: [RHEL-7 PATCH v3 01/15] qemu-kvm: Fix migration from older version due to i8254 changes +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Old qemu-kvm already contained an equivalent field to i8254's +irq_disabled. We therefore have to remove upstream's version restriction +here to allow migration from older versions. + +Signed-off-by: Jan Kiszka +Signed-off-by: Avi Kivity +(cherry picked from commit 81bdec908fb2be0ccaff1d4ee67956c509e440ad) + +Conflicts: + hw/i8254.c + +Picked from qemu-kvm-1.1. + +qemu-kvm-0.11.0 commit f69b3e2 added PITState member flags, added it +to migration section "i8254", and bumped its version to 2. + +qemu v0.12.0 commit 5122b43 ported i8254 to VMState, and also bumped +section version to 2. Version 2 now means different things in qemu +and qemu-kvm. + +This got merged into qemu-kvm-0.12.0 in commit f4f2edc. The merge +added migration of flags to qemu's code. Yet another version of +version 2. This is what we got in RHEL-6. + +qemu v1.1.0 commit ce967e2 added PITState member irq_disabled, +included it in migration section "i8254", and bumped its version to 3. +Because qemu's irq_disabled is compatible with qemu-kvm's flags, +qemu's version 3 is migration compatible with the latest instance of +qemu-kvm's version 2. + +When this got merged into qemu-kvm-1.1.0, it changed qemu-kvm's +version 2 to no longer include flags / irq_disabled. Commit 81bdec9 +reverted the change of version 2. + +We need to do the same to enable incoming migration from RHEL-6. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c +index 5342df4..f6f9d26 100644 +--- a/hw/timer/i8254_common.c ++++ b/hw/timer/i8254_common.c +@@ -275,7 +275,7 @@ static const VMStateDescription vmstate_pit_common = { + .pre_save = pit_dispatch_pre_save, + .post_load = pit_dispatch_post_load, + .fields = (VMStateField[]) { +- VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3), ++ VMSTATE_UINT32(channels[0].irq_disabled, PITCommonState), /* qemu-kvm's v2 had 'flags' here */ + VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2, + vmstate_pit_channel, PITChannelState), + VMSTATE_INT64(channels[0].next_transition_time, diff --git a/SOURCES/qemu.binfmt b/SOURCES/qemu.binfmt new file mode 100644 index 0000000..63a58f4 --- /dev/null +++ b/SOURCES/qemu.binfmt @@ -0,0 +1,17 @@ +:qemu-i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386: +:qemu-i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386: +:qemu-alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-alpha: +:qemu-arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm: +:qemu-armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb: +:qemu-sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc: +:qemu-ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc: +:qemu-m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k: +:qemu-mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips: +:qemu-mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel: +:qemu-mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mipsn32: +:qemu-mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsn32el: +:qemu-mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64: +:qemu-mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el: +:qemu-sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-sh4: +:qemu-sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sh4eb: +:qemu-s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-s390x: diff --git a/SOURCES/qxl-set-revision-to-1-for-rhel6-0-0.patch b/SOURCES/qxl-set-revision-to-1-for-rhel6-0-0.patch new file mode 100644 index 0000000..193694f --- /dev/null +++ b/SOURCES/qxl-set-revision-to-1-for-rhel6-0-0.patch @@ -0,0 +1,48 @@ +From e73cf28a72a02ce4f56471829a97c70dc4831a84 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:04:20 +0200 +Subject: qxl: set revision to 1 for rhel6.0.0 + +Message-id: <1375201922-6794-9-git-send-email-armbru@redhat.com> +Patchwork-id: 52818 +O-Subject: [RHEL-7 PATCH v3 08/15] qxl: set revision to 1 for rhel6.0.0 +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +From: Gerd Hoffmann + +bugzilla: #893344 - info qtree mismatch +upstream: No (rhel6.0.0 spice code base predates upstream merge, + so this compat property isn't relevant there). + +Signed-off-by: Gerd Hoffmann +Signed-off-by: Michal Novotny +(cherry picked from commit 69f07de9ed3678198578fe036da202cbbca3f312) + +Conflicts: + hw/pc.c + +Picked from qemu-kvm-rhel6. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 9e96b79..57877e3 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -870,11 +870,11 @@ static QEMUMachine pc_machine_rhel700 = { + },{\ + .driver = "qxl",\ + .property = "revision",\ +- .value = stringify(3),\ ++ .value = stringify(1),\ + },{\ + .driver = "qxl-vga",\ + .property = "revision",\ +- .value = stringify(3),\ ++ .value = stringify(1),\ + },{\ + .driver = "VGA",\ + .property = "mmio",\ diff --git a/SOURCES/rename-man-page-to-qemu-kvm.patch b/SOURCES/rename-man-page-to-qemu-kvm.patch new file mode 100644 index 0000000..455695f --- /dev/null +++ b/SOURCES/rename-man-page-to-qemu-kvm.patch @@ -0,0 +1,25 @@ +From 97decea4dd4ad5017ba64b5921030032108fa574 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 11 Apr 2013 10:28:14 +0200 +Subject: Rename man page qemu(1) to qemu-kvm(1). + +Bugzilla: 893318 + +We rename qemu binary to qemu-kvm so we need to change man page name accordingly. + +Signed-off-by: Miroslav Rezanina + +diff --git a/Makefile b/Makefile +index 46439f8..dbd96d1 100644 +--- a/Makefile ++++ b/Makefile +@@ -306,7 +306,7 @@ install-doc: $(DOCS) + $(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)" + ifdef CONFIG_POSIX + $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" +- $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1" ++ $(INSTALL_DATA) qemu.1 "$(DESTDIR)$(mandir)/man1/qemu-kvm.1" + ifneq ($(TOOLS),) + $(INSTALL_DATA) qemu-img.1 "$(DESTDIR)$(mandir)/man1" + $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8" + diff --git a/SOURCES/target-i386-set-level-4-on-conroe-penryn-nehalem.patch b/SOURCES/target-i386-set-level-4-on-conroe-penryn-nehalem.patch new file mode 100644 index 0000000..42b4704 --- /dev/null +++ b/SOURCES/target-i386-set-level-4-on-conroe-penryn-nehalem.patch @@ -0,0 +1,94 @@ +commit 2b70aa524d7d12a8662cf9fcf9d6ca6d0264b5a6 +Author: Eduardo Habkost +Date: Thu Jun 27 15:57:43 2013 +0200 + + target-i386: Set level=4 on Conroe/Penryn/Nehalem + + RH-Author: Eduardo Habkost + Message-id: <1372348663-1706-4-git-send-email-ehabkost@redhat.com> + Patchwork-id: 52253 + O-Subject: [PATCH v2 3/3] target-i386: Set level=4 on Conroe/Penryn/Nehalem + Bugzilla: 861210 + RH-Acked-by: Bandan Das + RH-Acked-by: Markus Armbruster + RH-Acked-by: Paolo Bonzini + + Bugzilla: 861210 + (cherry picked from commit 6b11322e0f724eb0649fdc324a44288b783023ad) + + The CPUID level value on Conroe, Penryn, and Nehalem are too low. This + causes at least one known problem: the -smp "threads" option doesn't + work as expect if level is < 4, because thread count information is + provided to the guest on CPUID[EAX=4,ECX=2].EAX + + Signed-off-by: Eduardo Habkost + Signed-off-by: Andreas Färber + Signed-off-by: Eduardo Habkost + --- + include/hw/i386/pc.h | 12 ++++++++++++ + target-i386/cpu.c | 6 +++--- + 2 files changed, 15 insertions(+), 3 deletions(-) + + Signed-off-by: Miroslav Rezanina + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 4d6c9bf..6692728 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -192,13 +192,25 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t); + .property = "model",\ + .value = stringify(2),\ + },{\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ + .driver = "Penryn-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ + },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ ++ },{\ + .driver = "Nehalem-" TYPE_X86_CPU,\ + .property = "model",\ + .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "level",\ ++ .value = stringify(2),\ + } + + #define PC_COMPAT_1_4 \ +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index 012819a..4b2da0d 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -669,7 +669,7 @@ static x86_def_t builtin_x86_defs[] = { + }, + { + .name = "Conroe", +- .level = 2, ++ .level = 4, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 15, +@@ -691,7 +691,7 @@ static x86_def_t builtin_x86_defs[] = { + }, + { + .name = "Penryn", +- .level = 2, ++ .level = 4, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 23, +@@ -714,7 +714,7 @@ static x86_def_t builtin_x86_defs[] = { + }, + { + .name = "Nehalem", +- .level = 2, ++ .level = 4, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 26, diff --git a/SOURCES/target-i386-update-model-values-on-conroe-penryn-nehalem-cpu-models.patch b/SOURCES/target-i386-update-model-values-on-conroe-penryn-nehalem-cpu-models.patch new file mode 100644 index 0000000..0813fda --- /dev/null +++ b/SOURCES/target-i386-update-model-values-on-conroe-penryn-nehalem-cpu-models.patch @@ -0,0 +1,131 @@ +commit 891c6ba393323686ace2b5ecd9c35bbde6165f2a +Author: Eduardo Habkost +Date: Thu Jun 27 15:57:42 2013 +0200 + + target-i386: Update model values on Conroe/Penryn/Nehalem CPU models + + RH-Author: Eduardo Habkost + Message-id: <1372348663-1706-3-git-send-email-ehabkost@redhat.com> + Patchwork-id: 52252 + O-Subject: [PATCH v2 2/3] target-i386: Update model values on Conroe/Penryn/Nehalem CPU models + Bugzilla: 861210 + RH-Acked-by: Bandan Das + RH-Acked-by: Markus Armbruster + RH-Acked-by: Paolo Bonzini + + Bugzilla: 861210 + (cherry picked from commit ffce9ebbb69363dfe7605585cdad58ea3847edf4) + + The CPUID model values on Conroe, Penryn, and Nehalem are too + conservative and don't reflect the values found on real Conroe, Penryn, + and Nehalem CPUs. + + This causes at least one known problems: Windows XP disables sysenter + when (family == 6 && model <= 2), but Skype tries to use the sysenter + instruction anyway because it is reported as available on CPUID, making + it crash. + + This patch sets appropriate model values that correspond to real Conroe, + Penryn, and Nehalem CPUs. + + Signed-off-by: Eduardo Habkost + Signed-off-by: Andreas Färber + Signed-off-by: Eduardo Habkost + --- + hw/i386/pc_piix.c | 4 ++++ + hw/i386/pc_q35.c | 4 ++++ + include/hw/i386/pc.h | 16 ++++++++++++++++ + target-i386/cpu.c | 6 +++--- + 4 files changed, 27 insertions(+), 3 deletions(-) + + Signed-off-by: Miroslav Rezanina + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index d8d74a3..b52034d 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -338,6 +338,10 @@ static QEMUMachine pc_i440fx_machine_v1_5 = { + .hot_add_cpu = pc_hot_add_cpu, + .max_cpus = 255, + .is_default = 1, ++ .compat_props = (GlobalProperty[]) { ++ PC_COMPAT_1_5, ++ { /* end of list */ } ++ }, + DEFAULT_MACHINE_OPTIONS, + }; + +diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c +index 9bcad00..0092032 100644 +--- a/hw/i386/pc_q35.c ++++ b/hw/i386/pc_q35.c +@@ -224,6 +224,10 @@ static QEMUMachine pc_q35_machine_v1_5 = { + .init = pc_q35_init, + .hot_add_cpu = pc_hot_add_cpu, + .max_cpus = 255, ++ .compat_props = (GlobalProperty[]) { ++ PC_COMPAT_1_5, ++ { /* end of list */ } ++ }, + DEFAULT_MACHINE_OPTIONS, + }; + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 0242fec..4d6c9bf 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -186,7 +186,23 @@ int pvpanic_init(ISABus *bus); + + int e820_add_entry(uint64_t, uint64_t, uint32_t); + ++#define PC_COMPAT_1_5 \ ++ {\ ++ .driver = "Conroe-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Penryn-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ },{\ ++ .driver = "Nehalem-" TYPE_X86_CPU,\ ++ .property = "model",\ ++ .value = stringify(2),\ ++ } ++ + #define PC_COMPAT_1_4 \ ++ PC_COMPAT_1_5, \ + {\ + .driver = "scsi-hd",\ + .property = "discard_granularity",\ +diff --git a/target-i386/cpu.c b/target-i386/cpu.c +index ae8e682..012819a 100644 +--- a/target-i386/cpu.c ++++ b/target-i386/cpu.c +@@ -672,7 +672,7 @@ static x86_def_t builtin_x86_defs[] = { + .level = 2, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +- .model = 2, ++ .model = 15, + .stepping = 3, + .features[FEAT_1_EDX] = + CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | +@@ -694,7 +694,7 @@ static x86_def_t builtin_x86_defs[] = { + .level = 2, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +- .model = 2, ++ .model = 23, + .stepping = 3, + .features[FEAT_1_EDX] = + CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | +@@ -717,7 +717,7 @@ static x86_def_t builtin_x86_defs[] = { + .level = 2, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, +- .model = 2, ++ .model = 26, + .stepping = 3, + .features[FEAT_1_EDX] = + CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | diff --git a/SOURCES/use-kvm-by-default.patch b/SOURCES/use-kvm-by-default.patch new file mode 100644 index 0000000..33eae0d --- /dev/null +++ b/SOURCES/use-kvm-by-default.patch @@ -0,0 +1,24 @@ +From 0eae445a8da5d9598af0c4419fa7fa94fc896f22 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 4 Apr 2013 11:00:41 +0200 +Subject: Use kvm by default + +Bugzilla: 906185 + +RHEL uses kvm accelerator by default, if available. + +Signed-off-by: Miroslav Rezanina + +diff --git a/vl.c b/vl.c +index 59dc0b4..6526c22 100644 +--- a/vl.c ++++ b/vl.c +@@ -2655,7 +2655,7 @@ static int configure_accelerator(void) + + if (p == NULL) { + /* Use the default "accelerator", tcg */ +- p = "tcg"; ++ p = "kvm:tcg"; + } + + while (!accel_initialised && *p != '\0') { diff --git a/SOURCES/vga-Default-vram_size_mb-to-16-like-prior-versions-of-RHEL.patch b/SOURCES/vga-Default-vram_size_mb-to-16-like-prior-versions-of-RHEL.patch new file mode 100644 index 0000000..7c8e8ca --- /dev/null +++ b/SOURCES/vga-Default-vram_size_mb-to-16-like-prior-versions-of-RHEL.patch @@ -0,0 +1,103 @@ +From c712cf32b457f67d926b3d54c015371d6683099b Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 08:02:53 +0200 +Subject: vga: Default .vram_size_mb to 16, like prior versions of RHEL + +Message-id: <1375201922-6794-5-git-send-email-armbru@redhat.com> +Patchwork-id: 52811 +O-Subject: [RHEL-7 PATCH v3 04/15] vga: Default .vram_size_mb to 16, like prior versions of RHEL +Bugzilla: 983991 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +A brief history of VGA video RAM sizes: + +* Initially, all VGA devices got 8 MiB of video RAM. + +* Upstream qemu-kvm kvm-62 (2008) doubled it to 16 MiB (commit + a7fe029). + +* RHEL-5 and RHEL-6 based on upstream qemu-kvm. + +* Upstream qemu v1.2.0 made the size configurable for "isa-vga", + "VGA", "vmware_vga" (commit 4a1e244), and "qxl-vga", "qxl" (commit + 13d1fd4), then doubled the default to 16 MiB (commit 9e56edc) for + the new machine type. Except "isa-vga" stayed at 8 MiB. + +* Upstream qemu-kvm merged this in qemu-kvm-1.2.0. Incompatible + change of default VGA video RAM back to 8 MiB for "isa-vga", + "isa-cirrus-vga", "cirrus-vga"[*]. + +* Upstream qemu v1.3.0 made the size configurable for + "isa-cirrus-vga", "cirrus-vga" (commit 19403a6). + +RHEL-7 bases on upstream qemu. To avoid qemu-kvm-1.2.0's incompatible +change, default video RAM size to 16 MiB for all VGA devices[**] and +RHEL machine types. + +[*] And the non-qdevified, memory-mapped VGA used by MIPS magnum and +pica61 machines, but these don't matter in qemu-kvm. + +[**] Except for the non-qdevified, memory-mapped VGA. + +Signed-off-by: Markus Armbruster + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index 64bfe2b..fa8eae2 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -2924,7 +2924,7 @@ static int vga_initfn(ISADevice *dev) + + static Property isa_cirrus_vga_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, +- cirrus_vga.vga.vram_size_mb, 8), ++ cirrus_vga.vga.vram_size_mb, 16), + DEFINE_PROP_END_OF_LIST(), + }; + +@@ -2986,7 +2986,7 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) + + static Property pci_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, +- cirrus_vga.vga.vram_size_mb, 8), ++ cirrus_vga.vga.vram_size_mb, 16), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c +index 9e63b69..2f34ee3 100644 +--- a/hw/display/vga-isa.c ++++ b/hw/display/vga-isa.c +@@ -75,7 +75,7 @@ static int vga_initfn(ISADevice *dev) + } + + static Property vga_isa_properties[] = { +- DEFINE_PROP_UINT32("vgamem_mb", ISAVGAState, state.vram_size_mb, 8), ++ DEFINE_PROP_UINT32("vgamem_mb", ISAVGAState, state.vram_size_mb, 16), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c +index 96f6bf9..5d57a76 100644 +--- a/hw/i386/pc_piix.c ++++ b/hw/i386/pc_piix.c +@@ -888,18 +888,6 @@ static QEMUMachine pc_machine_rhel700 = { + .property = "param_change",\ + .value = "off",\ + },{\ +- .driver = "VGA",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ +- .driver = "qxl-vga",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ +- .driver = "qxl",\ +- .property = "vgamem_mb",\ +- .value = stringify(8),\ +- },{\ + .driver = "virtio-blk-pci",\ + .property = "config-wce",\ + .value = "off",\ diff --git a/SOURCES/vmdk-Allow-reading-variable-size-descriptor-files.patch b/SOURCES/vmdk-Allow-reading-variable-size-descriptor-files.patch new file mode 100644 index 0000000..f26db11 --- /dev/null +++ b/SOURCES/vmdk-Allow-reading-variable-size-descriptor-files.patch @@ -0,0 +1,77 @@ +From 99ad3018eac4089569f5ccbc84737dce8e92384f Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 09:54:07 +0200 +Subject: vmdk: Allow reading variable size descriptor files + +Message-id: <1374654509-5535-3-git-send-email-famz@redhat.com> +Patchwork-id: 52674 +O-Subject: [RHEL-7 qemu-kvm PATCH 2/5] vmdk: Allow reading variable size descriptor files +Bugzilla: 836675 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Jeffrey Cody + +From: Evgeny Budilovsky + +the hard-coded 2k buffer on the stack won't allow reading big descriptor +files which can be generated when storing big images. For example 500G +vmdk splitted to 2G chunks. + +Signed-off-by: Evgeny Budilovsky +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Kevin Wolf +(cherry picked from commit 0bed087df24c7b3fae366f239b9d150de3309416) +Signed-off-by: Fam Zheng + +diff --git a/block/vmdk.c b/block/vmdk.c +index ee50a73..65ae011 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -722,27 +722,40 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + int64_t desc_offset) + { + int ret; +- char buf[2048]; ++ char *buf = NULL; + char ct[128]; + BDRVVmdkState *s = bs->opaque; ++ int64_t size; + +- ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf)); ++ size = bdrv_getlength(bs->file); ++ if (size < 0) { ++ return -EINVAL; ++ } ++ ++ size = MIN(size, 1 << 20); /* avoid unbounded allocation */ ++ buf = g_malloc0(size + 1); ++ ++ ret = bdrv_pread(bs->file, desc_offset, buf, size); + if (ret < 0) { +- return ret; ++ goto exit; + } +- buf[2047] = '\0'; + if (vmdk_parse_description(buf, "createType", ct, sizeof(ct))) { +- return -EMEDIUMTYPE; ++ ret = -EMEDIUMTYPE; ++ goto exit; + } + if (strcmp(ct, "monolithicFlat") && + strcmp(ct, "twoGbMaxExtentSparse") && + strcmp(ct, "twoGbMaxExtentFlat")) { + fprintf(stderr, + "VMDK: Not supported image type \"%s\""".\n", ct); +- return -ENOTSUP; ++ ret = -ENOTSUP; ++ goto exit; + } + s->desc_offset = 0; +- return vmdk_parse_extents(buf, bs, bs->file->filename); ++ ret = vmdk_parse_extents(buf, bs, bs->file->filename); ++exit: ++ g_free(buf); ++ return ret; + } + + static int vmdk_open(BlockDriverState *bs, QDict *options, int flags) diff --git a/SOURCES/vmdk-refuse-to-open-higher-version-than-supported.patch b/SOURCES/vmdk-refuse-to-open-higher-version-than-supported.patch new file mode 100644 index 0000000..52b60f4 --- /dev/null +++ b/SOURCES/vmdk-refuse-to-open-higher-version-than-supported.patch @@ -0,0 +1,46 @@ +From 06989fa543551f16e41b0218e10125df31ccbc0b Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 31 Jul 2013 09:54:55 +0200 +Subject: vmdk: refuse to open higher version than supported + +Message-id: <1374654509-5535-4-git-send-email-famz@redhat.com> +Patchwork-id: 52675 +O-Subject: [RHEL-7 qemu-kvm PATCH 3/5] vmdk: refuse to open higher version than supported +Bugzilla: 836675 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Jeffrey Cody +RH-Acked-by: Michal Novotny + +Refuse to open higher version for safety. + +Although we try to be compatible with published VMDK spec, VMware has +newer version from ESXi 5.1 exported OVF/OVA, which we have no knowledge +what's changed in it. And it is very likely to have more new versions in +the future, so it's not safe to open them blindly. + +Signed-off-by: Fam Zheng +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 96c51eb5e46af2312b33f745ad72acb20e799aea) +Signed-off-by: Fam Zheng + +diff --git a/block/vmdk.c b/block/vmdk.c +index 65ae011..975e1d4 100644 +--- a/block/vmdk.c ++++ b/block/vmdk.c +@@ -561,6 +561,15 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, + header = footer.header; + } + ++ if (le32_to_cpu(header.version) >= 3) { ++ char buf[64]; ++ snprintf(buf, sizeof(buf), "VMDK version %d", ++ le32_to_cpu(header.version)); ++ qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, ++ bs->device_name, "vmdk", buf); ++ return -ENOTSUP; ++ } ++ + l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) + * le64_to_cpu(header.granularity); + if (l1_entry_sectors == 0) { diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec new file mode 100644 index 0000000..dad5c30 --- /dev/null +++ b/SPECS/qemu-kvm.spec @@ -0,0 +1,3747 @@ +# Build time setting +%define rhev 0 + +%if %{rhev} + %bcond_with guest_agent # disabled +%else + %bcond_without guest_agent # enabled +%endif + +%global SLOF_gittagdate 20120731 + +%global have_usbredir 1 + +%ifarch %{ix86} x86_64 + %global have_seccomp 1 + %global have_spice 1 +%else + %global have_usbredir 0 +%endif + +%ifnarch x86_64 + %global build_only_sub 1 + %global debug_package %{nil} +%endif + +%ifarch %{ix86} + %global kvm_target i386 +%endif +%ifarch x86_64 + %global kvm_target x86_64 +%endif +%ifarch ppc64 + %global kvm_target ppc64 +%endif +%ifarch s390x + %global kvm_target s390x +%endif + +#Versions of various parts: + +%define pkgname qemu-kvm +%define rhel_suffix -rhel +%define rhev_suffix -rhev + +# Setup for RHEL/RHEV package handling +# We need to define tree suffixes: +# - pkgsuffix: used for package name +# - extra_provides_suffix: used for dependency checking of other packages +# - conflicts_suffix: used to prevent installation of both RHEL and RHEV + +%if %{rhev} + %global pkgsuffix %{rhev_suffix} + %global extra_provides_suffix %{nil} + %global conflicts_suffix %{rhel_suffix} + %global obsoletes_version 15:0-0 +%else + %global pkgsuffix %{nil} + %global extra_provides_suffix %{rhel_suffix} + %global conflicts_suffix %{rhev_suffix} +%endif + +# Macro to properly setup RHEL/RHEV conflict handling +%define rhel_rhev_conflicts() \ +Conflicts: %1%{conflicts_suffix} \ +Provides: %1%{extra_provides_suffix} = %{epoch}:%{version}-%{release} \ + %if 0%{?obsoletes_version:1} \ +Obsoletes: %1 < %{obsoletes_version} \ + %endif + +Summary: QEMU is a FAST! processor emulator +Name: %{pkgname}%{?pkgsuffix} +Version: 1.5.3 +Release: 19%{?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 +Group: Development/Tools +URL: http://www.qemu.org/ +# RHEV will build Qemu only on x86_64: +%if %{rhev} +ExclusiveArch: x86_64 +%endif +Requires: seabios-bin +Requires: sgabios-bin +Requires: seavgabios-bin +Requires: ipxe-roms-qemu +Requires: %{pkgname}-common%{?pkgsuffix} = %{epoch}:%{version}-%{release} + %if 0%{?have_seccomp:1} +Requires: libseccomp >= 1.0.0 + %endif + +# OOM killer breaks builds with parallel make on s390(x) +%ifarch s390 s390x + %define _smp_mflags %{nil} +%endif + +Source0: http://wiki.qemu-project.org/download/qemu-%{version}.tar.bz2 + +Source1: qemu.binfmt +# Loads kvm kernel modules at boot +# Not needed anymore - required only for kvm on non i86 archs +# where we do not ubuild kvm +# Source2: kvm.modules +# Creates /dev/kvm +Source3: 80-kvm.rules +# KSM control scripts +Source4: ksm.service +Source5: ksm.sysconfig +Source6: ksmctl.c +Source7: ksmtuned.service +Source8: ksmtuned +Source9: ksmtuned.conf +Source10: qemu-guest-agent.service +Source11: 99-qemu-guest-agent.rules +Source12: bridge.conf +Source13: qemu-ga.sysconfig +Source14: rhel6-virtio.rom +Source15: rhel6-pcnet.rom +Source16: rhel6-rtl8139.rom +Source17: rhel6-ne2k_pci.rom + +# libcacard build fixes (heading upstream) +Patch1: 0000-libcacard-fix-missing-symbols-in-libcacard.so.patch + +# Fix migration from qemu-kvm 1.2 to qemu 1.3 +#Patch3: 0002-Fix-migration-from-qemu-kvm-1.2.patch + +# Flow control series +#Patch4: 0100-char-Split-out-tcp-socket-close-code-in-a-separate-f.patch +#Patch5: 0101-char-Add-a-QemuChrHandlers-struct-to-initialise-char.patch +#Patch6: 0102-iohandlers-Add-enable-disable_write_fd_handler-funct.patch +#Patch7: 0103-char-Add-framework-for-a-write-unblocked-callback.patch +#Patch8: 0104-char-Update-send_all-to-handle-nonblocking-chardev-w.patch +#Patch9: 0105-char-Equip-the-unix-tcp-backend-to-handle-nonblockin.patch +#Patch10: 0106-char-Throttle-when-host-connection-is-down.patch +#Patch11: 0107-virtio-console-Enable-port-throttling-when-chardev-i.patch +#Patch12: 0108-spice-qemu-char.c-add-throttling.patch +#Patch13: 0109-spice-qemu-char.c-remove-intermediate-buffer.patch +#Patch14: 0110-usb-redir-Add-flow-control-support.patch +#Patch15: 0111-char-Disable-write-callback-if-throttled-chardev-is-.patch +#Patch16: 0112-hw-virtio-serial-bus-replay-guest-open-on-destinatio.patch + +# Migration compatibility +#Patch17: configure-add-enable-migration-from-qemu-kvm.patch +#Patch18: acpi_piix4-condition-on-minimum_version_id.patch +#Patch19: i8254-fix-migration-from-qemu-kvm-1.1.patch +#Patch20: pc_piix-add-compat-handling-for-qemu-kvm-vga-mem-size.patch +#Patch21: qxl-add-rom_size-compat-property.patch +#Patch22: docs-fix-generating-qemu-doc.html-with-texinfo5.patch +#Patch23: rtc-test-Fix-test-failures-with-recent-glib.patch +#Patch24: iscsi-look-for-pkg-config-file-too.patch +#Patch25: tcg-fix-occcasional-tcg-broken-problem.patch +#Patch26: qxl-better-vga-init-in-enter_vga_mode.patch + +# Enable/disable supported features +#Patch27: make-usb-devices-configurable.patch +#Patch28: fix-scripts-make_device_config-sh.patch +Patch29: disable-unsupported-usb-devices.patch +Patch30: disable-unsupported-emulated-scsi-devices.patch +Patch31: disable-various-unsupported-devices.patch +Patch32: disable-unsupported-audio-devices.patch +Patch33: disable-unsupported-emulated-network-devices.patch +Patch34: use-kvm-by-default.patch +Patch35: disable-hpet-device.patch +Patch36: rename-man-page-to-qemu-kvm.patch +Patch37: change-path-from-qemu-to-qemu-kvm.patch + +# Fix CPUID model/level values on Conroe/Penryn/Nehalem CPU models +Patch38: pc-replace-upstream-machine-types-by-rhel7-types.patch +Patch39: target-i386-update-model-values-on-conroe-penryn-nehalem-cpu-models.patch +Patch40: target-i386-set-level-4-on-conroe-penryn-nehalem.patch + +# RHEL guest( sata disk ) can not boot up (rhbz #981723) +#Patch41: ahci-Fix-FLUSH-command.patch +# Kill the "use flash device for BIOS unless KVM" misfeature (rhbz #963280) +Patch42: pc-Disable-the-use-flash-device-for-BIOS-unless-KVM-misfeature.patch +# Provide RHEL-6 machine types (rhbz #983991) +Patch43: qemu-kvm-Fix-migration-from-older-version-due-to-i8254-changes.patch +Patch44: pc-Add-machine-type-rhel6-0-0.patch +Patch45: pc-Drop-superfluous-RHEL-6-compat_props.patch +Patch46: vga-Default-vram_size_mb-to-16-like-prior-versions-of-RHEL.patch +Patch47: pc-Drop-RHEL-6-USB-device-compat_prop-full-path.patch +Patch48: pc-Drop-RHEL-6-compat_props-virtio-serial-pci-max_ports-vectors.patch +Patch49: pc-Drop-RHEL-6-compat_props-apic-kvm-apic-vapic.patch +Patch50: qxl-set-revision-to-1-for-rhel6-0-0.patch +Patch51: pc-Give-rhel6-0-0-a-kvmclock.patch +Patch52: pc-Add-machine-type-rhel6-1-0.patch +Patch53: pc-Add-machine-type-rhel6-2-0.patch +Patch54: pc-Add-machine-type-rhel6-3-0.patch +Patch55: pc-Add-machine-type-rhel6-4-0.patch +Patch56: pc-Add-machine-type-rhel6-5-0.patch +Patch57: e1000-Keep-capabilities-list-bit-on-for-older-RHEL-machine-types.patch +# Change s3/s4 default to "disable". (rhbz #980840) +Patch58: misc-disable-s3-s4-by-default.patch +Patch59: pc-rhel6-compat-enable-S3-S4-for-6-1-and-lower-machine-types.patch +# Support Virtual Memory Disk Format in qemu (rhbz #836675) +Patch60: vmdk-Allow-reading-variable-size-descriptor-files.patch +Patch61: vmdk-refuse-to-open-higher-version-than-supported.patch +#Patch62: vmdk-remove-wrong-calculation-of-relative-path.patch +Patch63: block-add-block-driver-read-only-whitelist.patch + +# query mem info from monitor would cause qemu-kvm hang [RHEL-7] (rhbz #970047) +Patch64: kvm-char-io_channel_send-don-t-lose-written-bytes.patch +Patch65: kvm-monitor-maintain-at-most-one-G_IO_OUT-watch.patch +# Throttle-down guest to help with live migration convergence (backport to RHEL7.0) (rhbz #985958) +Patch66: kvm-misc-Introduce-async_run_on_cpu.patch +Patch67: kvm-misc-Add-auto-converge-migration-capability.patch +Patch68: kvm-misc-Force-auto-convegence-of-live-migration.patch +# disable (for now) EFI-enabled roms (rhbz #962563) +Patch69: kvm-misc-Disable-EFI-enabled-roms.patch +# qemu-kvm "vPMU passthrough" mode breaks migration, shouldn't be enabled by default (rhbz #853101) +Patch70: kvm-target-i386-Pass-X86CPU-object-to-cpu_x86_find_by_name.patch +Patch71: kvm-target-i386-Disable-PMU-CPUID-leaf-by-default.patch +Patch72: kvm-pc-set-compat-pmu-property-for-rhel6-x-machine-types.patch +# Remove pending watches after virtserialport unplug (rhbz #992900) +# Patch73: kvm-virtio-console-Use-exitfn-for-virtserialport-too.patch +# Containment of error when an SR-IOV device encounters an error... (rhbz #984604) +Patch74: kvm-linux-headers-Update-to-v3-10-rc5.patch +Patch75: kvm-vfio-QEMU-AER-Qemu-changes-to-support-AER-for-VFIO-PCI-devices.patch + +# update qemu-ga config & init script in RHEL7 wrt. fsfreeze hook (rhbz 969942) +Patch76: kvm-misc-qga-fsfreeze-main-hook-adapt-to-RHEL-7-RH-only.patch +# RHEL7 does not have equivalent functionality for __com.redhat_qxl_screendump (rhbz 903910) +Patch77: kvm-misc-add-qxl_screendump-monitor-command.patch +# SEP flag behavior for CPU models of RHEL6 machine types should be compatible (rhbz 960216) +Patch78: kvm-pc_piix-disable-CPUID_SEP-for-6-4-0-machine-types-and-below.patch +# crash command can not read the dump-guest-memory file when paging=false [RHEL-7] (rhbz 981582) +Patch79: kvm-dump-Move-stubs-into-libqemustub-a.patch +Patch80: kvm-cpu-Turn-cpu_paging_enabled-into-a-CPUState-hook.patch +Patch81: kvm-memory_mapping-Move-MemoryMappingList-typedef-to-qemu-typedefs-h.patch +Patch82: kvm-cpu-Turn-cpu_get_memory_mapping-into-a-CPUState-hook.patch +Patch83: kvm-dump-Abstract-dump_init-with-cpu_synchronize_all_states.patch +Patch84: kvm-memory_mapping-Improve-qemu_get_guest_memory_mapping-error-reporting.patch +Patch85: kvm-dump-clamp-guest-provided-mapping-lengths-to-ramblock-sizes.patch +Patch86: kvm-dump-introduce-GuestPhysBlockList.patch +Patch87: kvm-dump-populate-guest_phys_blocks.patch +Patch88: kvm-dump-rebase-from-host-private-RAMBlock-offsets-to-guest-physical-addresses.patch +# RHEL 7 qemu-kvm fails to build on F19 host due to libusb deprecated API (rhbz 996469) +Patch89: kvm-usb-host-libusb-Fix-building-with-libusb-git-master-code.patch +# Live migration support in virtio-blk-data-plane (rhbz 995030) +#Patch90: kvm-dataplane-sync-virtio-c-and-vring-c-virtqueue-state.patch +#Patch91: kvm-virtio-clear-signalled_used_valid-when-switching-from-dataplane.patch +#Patch92: kvm-vhost-clear-signalled_used_valid-on-vhost-stop.patch +Patch93: kvm-migration-notify-migration-state-before-starting-thread.patch +Patch94: kvm-dataplane-enable-virtio-blk-x-data-plane-on-live-migration.patch +#Patch95: kvm-dataplane-refuse-to-start-if-device-is-already-in-use.patch +# qemu-img resize can execute successfully even input invalid syntax (rhbz 992935) +Patch96: kvm-qemu-img-Error-out-for-excess-arguments.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch97: kvm-osdep-add-qemu_get_local_state_pathname.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch98: kvm-qga-determine-default-state-dir-and-pidfile-dynamica.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch99: kvm-configure-don-t-save-any-fixed-local_statedir-for-wi.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch100: kvm-qga-create-state-directory-on-win32.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch101: kvm-qga-save-state-directory-in-ga_install_service-RHEL-.patch +# For bz#964304 - Windows guest agent service failed to be started +Patch102: kvm-Makefile-create-.-var-run-when-installing-the-POSIX-.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch103: kvm-qemu-option-Fix-qemu_opts_find-for-null-id-arguments.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch104: kvm-qemu-option-Fix-qemu_opts_set_defaults-for-corner-ca.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch105: kvm-vl-New-qemu_get_machine_opts.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch106: kvm-Fix-machine-options-accel-kernel_irqchip-kvm_shadow_.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch107: kvm-microblaze-Fix-latent-bug-with-default-DTB-lookup.patch +# For bz#980782 - kernel_irqchip defaults to off instead of on without -machine +Patch108: kvm-Simplify-machine-option-queries-with-qemu_get_machin.patch +# For bz#838170 - Add live migration support for USB [xhci, usb-uas] +Patch109: kvm-pci-add-VMSTATE_MSIX.patch +# For bz#838170 - Add live migration support for USB [xhci, usb-uas] +Patch110: kvm-xhci-add-XHCISlot-addressed.patch +# For bz#838170 - Add live migration support for USB [xhci, usb-uas] +Patch111: kvm-xhci-add-xhci_alloc_epctx.patch +# For bz#838170 - Add live migration support for USB [xhci, usb-uas] +Patch112: kvm-xhci-add-xhci_init_epctx.patch +# For bz#838170 - Add live migration support for USB [xhci, usb-uas] +Patch113: kvm-xhci-add-live-migration-support.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch114: kvm-pc-set-level-xlevel-correctly-on-486-qemu32-CPU-mode.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch115: kvm-pc-Remove-incorrect-rhel6.x-compat-model-value-for-C.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch116: kvm-pc-rhel6.x-has-x2apic-present-on-Conroe-Penryn-Nehal.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch117: kvm-pc-set-compat-CPUID-0x80000001-.EDX-bits-on-Westmere.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch118: kvm-pc-Remove-PCLMULQDQ-from-Westmere-on-rhel6.x-machine.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch119: kvm-pc-SandyBridge-rhel6.x-compat-fixes.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch120: kvm-pc-Haswell-doesn-t-have-rdtscp-on-rhel6.x.patch +# For bz#972433 - "INFO: rcu_sched detected stalls" after RHEL7 kvm vm migrated +Patch121: kvm-i386-fix-LAPIC-TSC-deadline-timer-save-restore.patch +# For bz#996258 - boot guest with maxcpu=255 successfully but actually max number of vcpu is 160 +Patch122: kvm-all.c-max_cpus-should-not-exceed-KVM-vcpu-limit.patch +# For bz#906937 - [Hitachi 7.0 FEAT][QEMU]Add a time stamp to error message (*) +Patch123: kvm-add-timestamp-to-error_report.patch +# For bz#906937 - [Hitachi 7.0 FEAT][QEMU]Add a time stamp to error message (*) +Patch124: kvm-Convert-stderr-message-calling-error_get_pretty-to-e.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch125: kvm-block-package-preparation-code-in-qmp_transaction.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch126: kvm-block-move-input-parsing-code-in-qmp_transaction.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch127: kvm-block-package-committing-code-in-qmp_transaction.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch128: kvm-block-package-rollback-code-in-qmp_transaction.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch129: kvm-block-make-all-steps-in-qmp_transaction-as-callback.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch130: kvm-blockdev-drop-redundant-proto_drv-check.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch131: kvm-block-Don-t-parse-protocol-from-file.filename.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch132: kvm-Revert-block-Disable-driver-specific-options-for-1.5.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch133: kvm-qcow2-Add-refcount-update-reason-to-all-callers.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch134: kvm-qcow2-Options-to-enable-discard-for-freed-clusters.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch135: kvm-qcow2-Batch-discards.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch136: kvm-block-Always-enable-discard-on-the-protocol-level.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch137: kvm-qapi.py-Avoid-code-duplication.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch138: kvm-qapi.py-Allow-top-level-type-reference-for-command-d.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch139: kvm-qapi-schema-Use-BlockdevSnapshot-type-for-blockdev-s.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch140: kvm-qapi-types.py-Implement-base-for-unions.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch141: kvm-qapi-visit.py-Split-off-generate_visit_struct_fields.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch142: kvm-qapi-visit.py-Implement-base-for-unions.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch143: kvm-docs-Document-QAPI-union-types.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch144: kvm-qapi-Add-visitor-for-implicit-structs.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch145: kvm-qapi-Flat-unions-with-arbitrary-discriminator.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch146: kvm-qapi-Add-consume-argument-to-qmp_input_get_object.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch147: kvm-qapi.py-Maintain-a-list-of-union-types.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch148: kvm-qapi-qapi-types.py-native-list-support.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch149: kvm-qapi-Anonymous-unions.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch150: kvm-block-Allow-driver-option-on-the-top-level.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch151: kvm-QemuOpts-Add-qemu_opt_unset.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch152: kvm-blockdev-Rename-I-O-throttling-options-for-QMP.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch153: kvm-qemu-iotests-Update-051-reference-output.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch154: kvm-blockdev-Rename-readonly-option-to-read-only.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch155: kvm-blockdev-Split-up-cache-option.patch +# For bz#1005818 - qcow2: Backport discard command line options +Patch156: kvm-qcow2-Use-dashes-instead-of-underscores-in-options.patch +# For bz#1006959 - qemu-iotests false positives +Patch157: kvm-qemu-iotests-filter-QEMU-version-in-monitor-banner.patch +# For bz#1006959 - qemu-iotests false positives +Patch158: kvm-tests-set-MALLOC_PERTURB_-to-expose-memory-bugs.patch +# For bz#1006959 - qemu-iotests false positives +Patch159: kvm-qemu-iotests-Whitespace-cleanup.patch +# For bz#1006959 - qemu-iotests false positives +Patch160: kvm-qemu-iotests-Fixed-test-case-026.patch +# For bz#1006959 - qemu-iotests false positives +Patch161: kvm-qemu-iotests-Fix-test-038.patch +# For bz#1006959 - qemu-iotests false positives +Patch162: kvm-qemu-iotests-Remove-lsi53c895a-tests-from-051.patch +# For bz#974887 - the screen of guest fail to display correctly when use spice + qxl driver +Patch163: kvm-spice-fix-display-initialization.patch +# For bz#921983 - Disable or remove emulated network devices that we will not support +Patch164: kvm-Remove-i82550-network-card-emulation.patch +# For bz#903914 - Disable or remove usb related devices that we will not support +Patch165: kvm-Remove-usb-wacom-tablet.patch +# For bz#903914 - Disable or remove usb related devices that we will not support +Patch166: kvm-Disable-usb-uas.patch +# For bz#947441 - HPET device must be disabled +Patch168: kvm-Remove-no-hpet-option.patch +# For bz#1002286 - Disable or remove device isa-parallel +Patch169: kvm-Disable-isa-parallel.patch +# For bz#949514 - fail to passthrough the USB3.0 stick to windows guest with xHCI controller under pc-i440fx-1.4 +Patch170: kvm-xhci-implement-warm-port-reset.patch +# For bz#953304 - Serial number of some USB devices must be fixed for older RHEL machine types +Patch171: kvm-usb-add-serial-bus-property.patch +# For bz#953304 - Serial number of some USB devices must be fixed for older RHEL machine types +Patch172: kvm-rhel6-compat-usb-serial-numbers.patch +# For bz#995866 - fix vmdk support to ESX images +Patch173: kvm-vmdk-fix-comment-for-vmdk_co_write_zeroes.patch +# For bz#1007226 - Introduce bs->zero_beyond_eof +Patch174: kvm-gluster-Add-image-resize-support.patch +# For bz#1007226 - Introduce bs->zero_beyond_eof +Patch175: kvm-block-Introduce-bs-zero_beyond_eof.patch +# For bz#1007226 - Introduce bs->zero_beyond_eof +Patch176: kvm-block-Produce-zeros-when-protocols-reading-beyond-en.patch +# For bz#1007226 - Introduce bs->zero_beyond_eof +Patch177: kvm-gluster-Abort-on-AIO-completion-failure.patch +# For bz#1001131 - Disable or remove device usb-bt-dongle +Patch178: kvm-Preparation-for-usb-bt-dongle-conditional-build.patch +# For bz#1001131 - Disable or remove device usb-bt-dongle +Patch179: kvm-Remove-dev-bluetooth.c-dependency-from-vl.c.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch180: kvm-exec-Fix-Xen-RAM-allocation-with-unusual-options.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch181: kvm-exec-Clean-up-fall-back-when-mem-path-allocation-fai.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch182: kvm-exec-Reduce-ifdeffery-around-mem-path.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch183: kvm-exec-Simplify-the-guest-physical-memory-allocation-h.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch184: kvm-exec-Drop-incorrect-dead-S390-code-in-qemu_ram_remap.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch185: kvm-exec-Clean-up-unnecessary-S390-ifdeffery.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch186: kvm-exec-Don-t-abort-when-we-can-t-allocate-guest-memory.patch +# For bz#1009328 - [RFE] Nicer error report when qemu-kvm can't allocate guest RAM +Patch187: kvm-pc_sysfw-Fix-ISA-BIOS-init-for-ridiculously-big-flas.patch +# For bz#903918 - Disable or remove emulated SCSI devices we will not support +Patch188: kvm-virtio-scsi-Make-type-virtio-scsi-common-abstract.patch +# For bz#1009491 - move qga logfiles to new /var/log/qemu-ga/ directory [RHEL-7] +Patch189: kvm-qga-move-logfiles-to-new-directory-for-easier-SELinu.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch190: kvm-target-i386-add-cpu64-rhel6-CPU-model.patch +# For bz#903889 - The value of steal time in "top" command always is "0.0% st" after guest migration +Patch191: kvm-fix-steal-time-MSR-vmsd-callback-to-proper-opaque-ty.patch +# For bz#995866 - fix vmdk support to ESX images +Patch192: kvm-vmdk-Make-VMDK3Header-and-VmdkGrainMarker-QEMU_PACKE.patch +# For bz#995866 - fix vmdk support to ESX images +Patch193: kvm-vmdk-use-unsigned-values-for-on-disk-header-fields.patch +# For bz#995866 - fix vmdk support to ESX images +Patch194: kvm-qemu-iotests-add-poke_file-utility-function.patch +# For bz#995866 - fix vmdk support to ESX images +Patch195: kvm-qemu-iotests-add-empty-test-case-for-vmdk.patch +# For bz#995866 - fix vmdk support to ESX images +Patch196: kvm-vmdk-check-granularity-field-in-opening.patch +# For bz#995866 - fix vmdk support to ESX images +Patch197: kvm-vmdk-check-l2-table-size-when-opening.patch +# For bz#995866 - fix vmdk support to ESX images +Patch198: kvm-vmdk-check-l1-size-before-opening-image.patch +# For bz#995866 - fix vmdk support to ESX images +Patch199: kvm-vmdk-use-heap-allocation-for-whole_grain.patch +# For bz#995866 - fix vmdk support to ESX images +Patch200: kvm-vmdk-rename-num_gtes_per_gte-to-num_gtes_per_gt.patch +# For bz#995866 - fix vmdk support to ESX images +Patch201: kvm-vmdk-Move-l1_size-check-into-vmdk_add_extent.patch +# For bz#995866 - fix vmdk support to ESX images +Patch202: kvm-vmdk-fix-L1-and-L2-table-size-in-vmdk3-open.patch +# For bz#995866 - fix vmdk support to ESX images +Patch203: kvm-vmdk-support-vmfsSparse-files.patch +# For bz#995866 - fix vmdk support to ESX images +Patch204: kvm-vmdk-support-vmfs-files.patch +# For bz#1005036 - When using “-vga qxl” together with “-display vnc=:5” or “-display sdl” qemu displays pixel garbage +Patch205: kvm-qxl-fix-local-renderer.patch +# For bz#1008987 - pvticketlocks: add kvm feature kvm_pv_unhalt +Patch206: kvm-linux-headers-update-to-kernel-3.10.0-26.el7.patch +# For bz#1008987 - pvticketlocks: add kvm feature kvm_pv_unhalt +Patch207: kvm-target-i386-add-feature-kvm_pv_unhalt.patch +# For bz#1010881 - backport vcpu soft limit warning +Patch208: kvm-warn-if-num-cpus-is-greater-than-num-recommended.patch +# For bz#1007222 - QEMU core dumped when do hot-unplug virtio serial port during transfer file between host to guest with virtio serial through TCP socket +Patch209: kvm-char-move-backends-io-watch-tag-to-CharDriverState.patch +# For bz#1007222 - QEMU core dumped when do hot-unplug virtio serial port during transfer file between host to guest with virtio serial through TCP socket +Patch210: kvm-char-use-common-function-to-disable-callbacks-on-cha.patch +# For bz#1007222 - QEMU core dumped when do hot-unplug virtio serial port during transfer file between host to guest with virtio serial through TCP socket +Patch211: kvm-char-remove-watch-callback-on-chardev-detach-from-fr.patch +# For bz#1017049 - qemu-img refuses to open the vmdk format image its created +Patch212: kvm-block-don-t-lose-data-from-last-incomplete-sector.patch +# For bz#1017049 - qemu-img refuses to open the vmdk format image its created +Patch213: kvm-vmdk-fix-cluster-size-check-for-flat-extents.patch +# For bz#1017049 - qemu-img refuses to open the vmdk format image its created +Patch214: kvm-qemu-iotests-add-monolithicFlat-creation-test-to-059.patch +# For bz#1001604 - usb hub doesn't work properly (win7 sees downstream port #1 only). +Patch215: kvm-xhci-fix-endpoint-interval-calculation.patch +# For bz#1001604 - usb hub doesn't work properly (win7 sees downstream port #1 only). +Patch216: kvm-xhci-emulate-intr-endpoint-intervals-correctly.patch +# For bz#1001604 - usb hub doesn't work properly (win7 sees downstream port #1 only). +Patch217: kvm-xhci-reset-port-when-disabling-slot.patch +# For bz#1001604 - usb hub doesn't work properly (win7 sees downstream port #1 only). +Patch218: kvm-Revert-usb-hub-report-status-changes-only-once.patch +# For bz#1004290 - Use model 6 for qemu64 and intel cpus +Patch219: kvm-target-i386-Set-model-6-on-qemu64-qemu32-CPU-models.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch220: kvm-pc-rhel6-doesn-t-have-APIC-on-pentium-CPU-models.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch221: kvm-pc-RHEL-6-had-x2apic-set-on-Opteron_G-123.patch +# For bz#918907 - provide backwards-compatible RHEL specific machine types in QEMU - CPU features +Patch222: kvm-pc-RHEL-6-don-t-have-RDTSCP.patch +# For bz#1009285 - -device usb-storage,serial=... crashes with SCSI generic drive +Patch223: kvm-scsi-Fix-scsi_bus_legacy_add_drive-scsi-generic-with.patch +# For bz#1004175 - '-sandbox on' option cause qemu-kvm process hang +Patch224: kvm-seccomp-fine-tuning-whitelist-by-adding-times.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch225: kvm-block-add-bdrv_write_zeroes.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch226: kvm-block-raw-add-bdrv_co_write_zeroes.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch227: kvm-rdma-export-qemu_fflush.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch228: kvm-block-migration-efficiently-encode-zero-blocks.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch229: kvm-Fix-real-mode-guest-migration.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch230: kvm-Fix-real-mode-guest-segments-dpl-value-in-savevm.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch231: kvm-migration-add-autoconvergence-documentation.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch232: kvm-migration-send-total-time-in-QMP-at-completed-stage.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch233: kvm-migration-don-t-use-uninitialized-variables.patch +# For bz#921465 - Migration can not finished even the "remaining ram" is already 0 kb +Patch234: kvm-pc-drop-external-DSDT-loading.patch +# For bz#954195 - RHEL machines <=6.4 should not use mixemu +Patch235: kvm-hda-codec-refactor-common-definitions-into-a-header-.patch +# For bz#954195 - RHEL machines <=6.4 should not use mixemu +Patch236: kvm-hda-codec-make-mixemu-selectable-at-runtime.patch +# For bz#954195 - RHEL machines <=6.4 should not use mixemu +Patch237: kvm-audio-remove-CONFIG_MIXEMU-configure-option.patch +# For bz#954195 - RHEL machines <=6.4 should not use mixemu +Patch238: kvm-pc_piix-disable-mixer-for-6.4.0-machine-types-and-be.patch +# For bz#994414 - hot-unplug chardev with pty backend caused qemu Segmentation fault +Patch239: kvm-chardev-fix-pty_chr_timer.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch240: kvm-qemu-socket-zero-initialize-SocketAddress.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch241: kvm-qemu-socket-drop-pointless-allocation.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch242: kvm-qemu-socket-catch-monitor_get_fd-failures.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch243: kvm-qemu-char-check-optional-fields-using-has_.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch244: kvm-error-add-error_setg_file_open-helper.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch245: kvm-qemu-char-use-more-specific-error_setg_-variants.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch246: kvm-qemu-char-print-notification-to-stderr.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch247: kvm-qemu-char-fix-documentation-for-telnet-wait-socket-f.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch248: kvm-qemu-char-don-t-leak-opts-on-error.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch249: kvm-qemu-char-use-ChardevBackendKind-in-CharDriver.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch250: kvm-qemu-char-minor-mux-chardev-fixes.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch251: kvm-qemu-char-add-chardev-mux-support.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch252: kvm-qemu-char-report-udp-backend-errors.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch253: kvm-qemu-socket-don-t-leak-opts-on-error.patch +# For bz#922010 - RFE: support hotplugging chardev & serial ports +Patch254: kvm-chardev-handle-qmp_chardev_add-KIND_MUX-failure.patch +# For bz#1019474 - RHEL-7 can't load piix4_pm migration section from RHEL-6.5 +Patch255: kvm-acpi-piix4-Enable-qemu-kvm-compatibility-mode.patch +# For bz#1004743 - XSAVE migration format not compatible between RHEL6 and RHEL7 +Patch256: kvm-target-i386-support-loading-of-cpu-xsave-subsection.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch257: kvm-vl-Clean-up-parsing-of-boot-option-argument.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch258: kvm-qemu-option-check_params-is-now-unused-drop-it.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch259: kvm-vl-Fix-boot-order-and-once-regressions-and-related-b.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch260: kvm-vl-Rename-boot_devices-to-boot_order-for-consistency.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch261: kvm-pc-Make-no-fd-bootchk-stick-across-boot-order-change.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch262: kvm-doc-Drop-ref-to-Bochs-from-no-fd-bootchk-documentati.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch263: kvm-libqtest-Plug-fd-and-memory-leaks-in-qtest_quit.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch264: kvm-libqtest-New-qtest_end-to-go-with-qtest_start.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch265: kvm-qtest-Don-t-reset-on-qtest-chardev-connect.patch +# For bz#997817 - -boot order and -boot once regressed since RHEL-6 +Patch266: kvm-boot-order-test-New-covering-just-PC-for-now.patch +# For bz#1019352 - qemu-guest-agent: "guest-fsfreeze-freeze" deadlocks if the guest have mounted disk images +Patch267: kvm-qemu-ga-execute-fsfreeze-freeze-in-reverse-order-of-.patch +# For bz#989608 - [7.0 FEAT] qemu runtime support for librbd backend (ceph) +Patch268: kvm-rbd-link-and-load-librbd-dynamically.patch +# For bz#989608 - [7.0 FEAT] qemu runtime support for librbd backend (ceph) +Patch269: kvm-rbd-Only-look-for-qemu-specific-copy-of-librbd.so.1.patch +# For bz#989677 - [HP 7.0 FEAT]: Increase KVM guest supported memory to 4TiB +Patch270: kvm-seabios-paravirt-allow-more-than-1TB-in-x86-guest.patch +# For bz#1006468 - libiscsi initiator name should use vm UUID +Patch271: kvm-scsi-prefer-UUID-to-VM-name-for-the-initiator-name.patch +# For bz#928867 - Virtual PMU support during live migration - qemu-kvm +Patch272: kvm-target-i386-remove-tabs-from-target-i386-cpu.h.patch +# For bz#928867 - Virtual PMU support during live migration - qemu-kvm +Patch273: kvm-migrate-vPMU-state.patch +# For bz#1009993 - RHEL7 guests do not issue fdatasyncs on virtio-blk +Patch274: kvm-blockdev-do-not-default-cache.no-flush-to-true.patch +# For bz#1009993 - RHEL7 guests do not issue fdatasyncs on virtio-blk +Patch275: kvm-virtio-blk-do-not-relay-a-previous-driver-s-WCE-conf.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch276: kvm-rng-random-use-error_setg_file_open.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch277: kvm-block-mirror_complete-use-error_setg_file_open.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch278: kvm-blockdev-use-error_setg_file_open.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch279: kvm-cpus-use-error_setg_file_open.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch280: kvm-dump-qmp_dump_guest_memory-use-error_setg_file_open.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch281: kvm-savevm-qmp_xen_save_devices_state-use-error_setg_fil.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch282: kvm-block-bdrv_reopen_prepare-don-t-use-QERR_OPEN_FILE_F.patch +# For bz#907743 - qemu-ga: empty reason string for OpenFileFailed error +Patch283: kvm-qerror-drop-QERR_OPEN_FILE_FAILED-macro.patch +# For bz#787463 - disable ivshmem (was: [Hitachi 7.0 FEAT] Support ivshmem (Inter-VM Shared Memory)) +Patch284: kvm-rhel-Drop-ivshmem-device.patch +# For bz#1001144 - Disable or remove device usb-host-linux +Patch285: kvm-usb-remove-old-usb-host-code.patch +# For bz#997702 - Migration from RHEL6.5 host to RHEL7.0 host is failed with virtio-net device +Patch286: kvm-Fix-migration-from-rhel6.5-to-rhel7-with-ipxe.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch287: kvm-pc-Don-t-prematurely-explode-QEMUMachineInitArgs.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch288: kvm-pc-Don-t-explode-QEMUMachineInitArgs-into-local-vari.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch289: kvm-smbios-Normalize-smbios_entry_add-s-error-handling-t.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch290: kvm-smbios-Convert-to-QemuOpts.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch291: kvm-smbios-Improve-diagnostics-for-conflicting-entries.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch292: kvm-smbios-Make-multiple-smbios-type-accumulate-sanely.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch293: kvm-smbios-Factor-out-smbios_maybe_add_str.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch294: kvm-hw-Pass-QEMUMachine-to-its-init-method.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch295: kvm-smbios-Set-system-manufacturer-product-version-by-de.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch296: kvm-smbios-Decouple-system-product-from-QEMUMachine.patch +# For bz#994490 - Set per-machine-type SMBIOS strings +Patch297: kvm-rhel-SMBIOS-type-1-branding.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch298: kvm-cow-make-reads-go-at-a-decent-speed.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch299: kvm-cow-make-writes-go-at-a-less-indecent-speed.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch300: kvm-cow-do-not-call-bdrv_co_is_allocated.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch301: kvm-block-keep-bs-total_sectors-up-to-date-even-for-grow.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch302: kvm-block-make-bdrv_co_is_allocated-static.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch303: kvm-block-do-not-use-total_sectors-in-bdrv_co_is_allocat.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch304: kvm-block-remove-bdrv_is_allocated_above-bdrv_co_is_allo.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch305: kvm-block-expect-errors-from-bdrv_co_is_allocated.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch306: kvm-block-Fix-compiler-warning-Werror-uninitialized.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch307: kvm-qemu-img-always-probe-the-input-image-for-allocated-.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch308: kvm-block-make-bdrv_has_zero_init-return-false-for-copy-.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch309: kvm-block-introduce-bdrv_get_block_status-API.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch310: kvm-block-define-get_block_status-return-value.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch311: kvm-block-return-get_block_status-data-and-flags-for-for.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch312: kvm-block-use-bdrv_has_zero_init-to-return-BDRV_BLOCK_ZE.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch313: kvm-block-return-BDRV_BLOCK_ZERO-past-end-of-backing-fil.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch314: kvm-qemu-img-add-a-map-subcommand.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch315: kvm-docs-qapi-document-qemu-img-map.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch316: kvm-raw-posix-return-get_block_status-data-and-flags.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch317: kvm-raw-posix-report-unwritten-extents-as-zero.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch318: kvm-block-add-default-get_block_status-implementation-fo.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch319: kvm-block-look-for-zero-blocks-in-bs-file.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch320: kvm-qemu-img-fix-invalid-JSON.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch321: kvm-block-get_block_status-set-pnum-0-on-error.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch322: kvm-block-get_block_status-avoid-segfault-if-there-is-no.patch +# For bz#989646 - Support backup vendors in qemu to access qcow disk readonly +Patch323: kvm-block-get_block_status-avoid-redundant-callouts-on-r.patch +# For bz#1025740 - Saving VM state on qcow2 images results in VM state corruption +Patch324: kvm-qcow2-Restore-total_sectors-value-in-save_vmstate.patch +# For bz#1025740 - Saving VM state on qcow2 images results in VM state corruption +Patch325: kvm-qcow2-Unset-zero_beyond_eof-in-save_vmstate.patch +# For bz#1025740 - Saving VM state on qcow2 images results in VM state corruption +Patch326: kvm-qemu-iotests-Test-for-loading-VM-state-from-qcow2.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch327: kvm-apic-rename-apic-specific-bitopts.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch328: kvm-hw-import-bitmap-operations-in-qdev-core-header.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch329: kvm-qemu-help-Sort-devices-by-logical-functionality.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch330: kvm-devices-Associate-devices-to-their-logical-category.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch331: kvm-Mostly-revert-qemu-help-Sort-devices-by-logical-func.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch332: kvm-qdev-monitor-Group-device_add-help-and-info-qdm-by-c.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch333: kvm-qdev-Replace-no_user-by-cannot_instantiate_with_devi.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch334: kvm-sysbus-Set-cannot_instantiate_with_device_add_yet.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch335: kvm-cpu-Document-why-cannot_instantiate_with_device_add_.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch336: kvm-apic-Document-why-cannot_instantiate_with_device_add.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch337: kvm-pci-host-Consistently-set-cannot_instantiate_with_de.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch338: kvm-ich9-Document-why-cannot_instantiate_with_device_add.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch339: kvm-piix3-piix4-Clean-up-use-of-cannot_instantiate_with_.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch340: kvm-vt82c686-Clean-up-use-of-cannot_instantiate_with_dev.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch341: kvm-isa-Clean-up-use-of-cannot_instantiate_with_device_a.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch342: kvm-qdev-Do-not-let-the-user-try-to-device_add-when-it-c.patch +# For bz#1001216 - Fix no_user or provide another way make devices unavailable with -device / device_add +Patch343: kvm-rhel-Revert-unwanted-cannot_instantiate_with_device_.patch +# For bz#1001076 - Disable or remove other block devices we won't support +Patch344: kvm-rhel-Revert-downstream-changes-to-unused-default-con.patch +# For bz#1001076 - Disable or remove other block devices we won't support +Patch345: kvm-rhel-Drop-cfi.pflash01-and-isa-ide-device.patch +# For bz#1001088 - Disable or remove display devices we won't support +Patch346: kvm-rhel-Drop-isa-vga-device.patch +# For bz#1001088 - Disable or remove display devices we won't support +Patch347: kvm-rhel-Make-isa-cirrus-vga-device-unavailable.patch +# For bz#1001123 - Disable or remove device ccid-card-emulated +Patch348: kvm-rhel-Make-ccid-card-emulated-device-unavailable.patch +# For bz#1005695 - QEMU should hide CPUID.0Dh values that it does not support +Patch349: kvm-x86-fix-migration-from-pre-version-12.patch +# For bz#1005695 - QEMU should hide CPUID.0Dh values that it does not support +Patch350: kvm-x86-cpuid-reconstruct-leaf-0Dh-data.patch +# For bz#920021 - qemu-kvm segment fault when reboot guest after hot unplug device with option ROM +Patch351: kvm-kvmvapic-Catch-invalid-ROM-size.patch +# For bz#920021 - qemu-kvm segment fault when reboot guest after hot unplug device with option ROM +Patch352: kvm-kvmvapic-Enter-inactive-state-on-hardware-reset.patch +# For bz#920021 - qemu-kvm segment fault when reboot guest after hot unplug device with option ROM +Patch353: kvm-kvmvapic-Clear-also-physical-ROM-address-when-enteri.patch +# For bz#987582 - Initial Virtualization Differentiation for RHEL7 (Live snapshots) +Patch354: kvm-block-optionally-disable-live-block-jobs.patch +# For bz#1022392 - Disable live-storage-migration in qemu-kvm (migrate -b/-i) +Patch355: kvm-migration-disable-live-block-migration-b-i-for-rhel-.patch +# For bz#987583 - Initial Virtualization Differentiation for RHEL7 (Ceph enablement) +Patch356: kvm-Build-ceph-rbd-only-for-rhev.patch +# For bz#1001180 - Disable or remove devices pci-serial-2x, pci-serial-4x +Patch357: kvm-rhel-Make-pci-serial-2x-and-pci-serial-4x-device-una.patch +# For bz#980415 - libusbx: error [_open_sysfs_attr] open /sys/bus/usb/devices/4-1/bConfigurationValue failed ret=-1 errno=2 +Patch358: kvm-usb-host-libusb-Fix-reset-handling.patch +# For bz#980383 - The usb3.0 stick can't be returned back to host after shutdown guest with usb3.0 pass-through +Patch359: kvm-usb-host-libusb-Configuration-0-may-be-a-valid-confi.patch +# For bz#980383 - The usb3.0 stick can't be returned back to host after shutdown guest with usb3.0 pass-through +Patch360: kvm-usb-host-libusb-Detach-kernel-drivers-earlier.patch +# For bz#1010858 - Disable unused human monitor commands +Patch361: kvm-monitor-Remove-pci_add-command-for-Red-Hat-Enterpris.patch +# For bz#1010858 - Disable unused human monitor commands +Patch362: kvm-monitor-Remove-pci_del-command-for-Red-Hat-Enterpris.patch +# For bz#1010858 - Disable unused human monitor commands +Patch363: kvm-monitor-Remove-usb_add-del-commands-for-Red-Hat-Ente.patch +# For bz#1010858 - Disable unused human monitor commands +Patch364: kvm-monitor-Remove-host_net_add-remove-for-Red-Hat-Enter.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch365: kvm-fw_cfg-add-API-to-find-FW-cfg-object.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch366: kvm-pvpanic-use-FWCfgState-explicitly.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch367: kvm-pvpanic-initialization-cleanup.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch368: kvm-pvpanic-fix-fwcfg-for-big-endian-hosts.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch369: kvm-hw-misc-make-pvpanic-known-to-user.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch370: kvm-gdbstub-do-not-restart-crashed-guest.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch371: kvm-gdbstub-fix-for-commit-87f25c12bfeaaa0c41fb857713bbc.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch372: kvm-vl-allow-cont-from-panicked-state.patch +# For bz#990601 - pvpanic device triggers guest bugs when present by default +Patch373: kvm-hw-misc-don-t-create-pvpanic-device-by-default.patch +# For bz#1007176 - Add VPC and VHDX file formats as supported in qemu-kvm (read-only) +Patch374: kvm-block-vhdx-add-migration-blocker.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch375: kvm-block-drop-bs_snapshots-global-variable.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch376: kvm-block-move-snapshot-code-in-block.c-to-block-snapsho.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch377: kvm-block-fix-vvfat-error-path-for-enable_write_target.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch378: kvm-block-Bugfix-format-and-snapshot-used-in-drive-optio.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch379: kvm-iscsi-use-bdrv_new-instead-of-stack-structure.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch380: kvm-qcow2-Add-corrupt-bit.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch381: kvm-qcow2-Metadata-overlap-checks.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch382: kvm-qcow2-Employ-metadata-overlap-checks.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch383: kvm-qcow2-refcount-Move-OFLAG_COPIED-checks.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch384: kvm-qcow2-refcount-Repair-OFLAG_COPIED-errors.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch385: kvm-qcow2-refcount-Repair-shared-refcount-blocks.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch386: kvm-qcow2_check-Mark-image-consistent.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch387: kvm-qemu-iotests-Overlapping-cluster-allocations.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch388: kvm-w32-Fix-access-to-host-devices-regression.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch389: kvm-add-qemu-img-convert-n-option-skip-target-volume-cre.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch390: kvm-bdrv-Use-Error-for-opening-images.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch391: kvm-bdrv-Use-Error-for-creating-images.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch392: kvm-block-Error-parameter-for-open-functions.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch393: kvm-block-Error-parameter-for-create-functions.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch394: kvm-qemu-img-create-Emit-filename-on-error.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch395: kvm-qcow2-Use-Error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch396: kvm-qemu-iotests-Adjustments-due-to-error-propagation.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch397: kvm-block-raw-Employ-error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch398: kvm-block-raw-win32-Employ-error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch399: kvm-blkdebug-Employ-error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch400: kvm-blkverify-Employ-error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch401: kvm-block-raw-posix-Employ-error-parameter.patch +# For bz#1026524 - Backport block layer error parameter patches +Patch402: kvm-block-raw-win32-Always-use-errno-in-hdev_open.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch403: kvm-qmp-Documentation-for-BLOCK_IMAGE_CORRUPTED.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch404: kvm-qcow2-Correct-snapshots-size-for-overlap-check.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch405: kvm-qcow2-CHECK_OFLAG_COPIED-is-obsolete.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch406: kvm-qcow2-Correct-endianness-in-overlap-check.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch407: kvm-qcow2-Switch-L1-table-in-a-single-sequence.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch408: kvm-qcow2-Use-pread-for-inactive-L1-in-overlap-check.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch409: kvm-qcow2-Remove-wrong-metadata-overlap-check.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch410: kvm-qcow2-Use-negated-overflow-check-mask.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch411: kvm-qcow2-Make-overlap-check-mask-variable.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch412: kvm-qcow2-Add-overlap-check-options.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch413: kvm-qcow2-Array-assigning-options-to-OL-check-bits.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch414: kvm-qcow2-Add-more-overlap-check-bitmask-macros.patch +# For bz#1004347 - Backport qcow2 corruption prevention patches +Patch415: kvm-qcow2-Evaluate-overlap-check-options.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch416: kvm-qapi-types.py-Split-off-generate_struct_fields.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch417: kvm-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch418: kvm-qapi-types-visit.py-Pass-whole-expr-dict-for-structs.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch419: kvm-qapi-types-visit.py-Inheritance-for-structs.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch420: kvm-blockdev-Introduce-DriveInfo.enable_auto_del.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch421: kvm-Implement-qdict_flatten.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch422: kvm-blockdev-blockdev-add-QMP-command.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch423: kvm-blockdev-Separate-ID-generation-from-DriveInfo-creat.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch424: kvm-blockdev-Pass-QDict-to-blockdev_init.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch425: kvm-blockdev-Move-parsing-of-media-option-to-drive_init.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch426: kvm-blockdev-Move-parsing-of-if-option-to-drive_init.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch427: kvm-blockdev-Moving-parsing-of-geometry-options-to-drive.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch428: kvm-blockdev-Move-parsing-of-boot-option-to-drive_init.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch429: kvm-blockdev-Move-bus-unit-index-processing-to-drive_ini.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch430: kvm-blockdev-Move-virtio-blk-device-creation-to-drive_in.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch431: kvm-blockdev-Remove-IF_-check-for-read-only-blockdev_ini.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch432: kvm-qemu-iotests-Check-autodel-behaviour-for-device_del.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch433: kvm-blockdev-Remove-media-parameter-from-blockdev_init.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch434: kvm-blockdev-Don-t-disable-COR-automatically-with-blockd.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch435: kvm-blockdev-blockdev_init-error-conversion.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch436: kvm-sd-Avoid-access-to-NULL-BlockDriverState.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch437: kvm-blockdev-fix-cdrom-read_only-flag.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch438: kvm-block-fix-backing-file-overriding.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch439: kvm-block-Disable-BDRV_O_COPY_ON_READ-for-the-backing-fi.patch +# For bz#978402 - [RFE] Add discard support to qemu-kvm layer +Patch440: kvm-block-Don-t-copy-backing-file-name-on-error.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch441: kvm-qemu-iotests-Try-creating-huge-qcow2-image.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch442: kvm-block-move-qmp-and-info-dump-related-code-to-block-q.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch443: kvm-block-dump-snapshot-and-image-info-to-specified-outp.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch444: kvm-block-add-snapshot-info-query-function-bdrv_query_sn.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch445: kvm-block-add-image-info-query-function-bdrv_query_image.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch446: kvm-qmp-add-ImageInfo-in-BlockDeviceInfo-used-by-query-b.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch447: kvm-vmdk-Implement-.bdrv_has_zero_init.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch448: kvm-qemu-iotests-Add-basic-ability-to-use-binary-sample-.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch449: kvm-qemu-iotests-Quote-TEST_IMG-and-TEST_DIR-usage.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch450: kvm-qemu-iotests-fix-test-case-059.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch451: kvm-qapi-Add-ImageInfoSpecific-type.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch452: kvm-block-Add-bdrv_get_specific_info.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch453: kvm-block-qapi-Human-readable-ImageInfoSpecific-dump.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch454: kvm-qcow2-Add-support-for-ImageInfoSpecific.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch455: kvm-qemu-iotests-Discard-specific-info-in-_img_info.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch456: kvm-qemu-iotests-Additional-info-from-qemu-img-info.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch457: kvm-vmdk-convert-error-code-to-use-errp.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch458: kvm-vmdk-refuse-enabling-zeroed-grain-with-flat-images.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch459: kvm-qapi-Add-optional-field-compressed-to-ImageInfo.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch460: kvm-vmdk-Only-read-cid-from-image-file-when-opening.patch +# For bz#980771 - [RFE] qemu-img should be able to tell the compat version of a qcow2 image +Patch461: kvm-vmdk-Implment-bdrv_get_specific_info.patch +# For bz#1025877 - pci-assign lacks MSI affinity support +Patch462: kvm-pci-assign-Add-MSI-affinity-support.patch +# For bz#1025877 - pci-assign lacks MSI affinity support +Patch463: kvm-Fix-potential-resource-leak-missing-fclose.patch +# For bz#1025877 - pci-assign lacks MSI affinity support +Patch464: kvm-pci-assign-remove-the-duplicate-function-name-in-deb.patch +# For bz#922589 - e1000/rtl8139: qemu mac address can not be changed via set the hardware address in guest +Patch465: kvm-net-update-nic-info-during-device-reset.patch +# For bz#922589 - e1000/rtl8139: qemu mac address can not be changed via set the hardware address in guest +Patch466: kvm-net-e1000-update-network-information-when-macaddr-is.patch +# For bz#922589 - e1000/rtl8139: qemu mac address can not be changed via set the hardware address in guest +Patch467: kvm-net-rtl8139-update-network-information-when-macaddr-.patch +# For bz#1026689 - virtio-net: macaddr is reset but network info of monitor isn't updated +Patch468: kvm-virtio-net-fix-up-HMP-NIC-info-string-on-reset.patch +# For bz#1025477 - VFIO MSI affinity +Patch469: kvm-vfio-pci-VGA-quirk-update.patch +# For bz#1025477 - VFIO MSI affinity +Patch470: kvm-vfio-pci-Add-support-for-MSI-affinity.patch +# For bz#1026550 - QEMU VFIO update ROM loading code +Patch471: kvm-vfio-pci-Test-device-reset-capabilities.patch +# For bz#1026550 - QEMU VFIO update ROM loading code +Patch472: kvm-vfio-pci-Lazy-PCI-option-ROM-loading.patch +# For bz#1026550 - QEMU VFIO update ROM loading code +Patch473: kvm-vfio-pci-Cleanup-error_reports.patch +# For bz#1026550 - QEMU VFIO update ROM loading code +Patch474: kvm-vfio-pci-Add-dummy-PCI-ROM-write-accessor.patch +# For bz#1026550 - QEMU VFIO update ROM loading code +Patch475: kvm-vfio-pci-Fix-endian-issues-in-vfio_pci_size_rom.patch +# For bz#1025472 - Nvidia GPU device assignment - qemu-kvm - bus reset support +Patch476: kvm-linux-headers-Update-to-include-vfio-pci-hot-reset-s.patch +# For bz#1025472 - Nvidia GPU device assignment - qemu-kvm - bus reset support +Patch477: kvm-vfio-pci-Implement-PCI-hot-reset.patch +# For bz#1025474 - Nvidia GPU device assignment - qemu-kvm - NoSnoop support +Patch478: kvm-linux-headers-Update-for-KVM-VFIO-device.patch +# For bz#1025474 - Nvidia GPU device assignment - qemu-kvm - NoSnoop support +Patch479: kvm-vfio-pci-Make-use-of-new-KVM-VFIO-device.patch +# For bz#995866 - fix vmdk support to ESX images +Patch480: kvm-vmdk-Fix-vmdk_parse_extents.patch +# For bz#995866 - fix vmdk support to ESX images +Patch481: kvm-vmdk-fix-VMFS-extent-parsing.patch +# For bz#922589 - e1000/rtl8139: qemu mac address can not be changed via set the hardware address in guest +#Patch482: kvm-e1000-rtl8139-update-HMP-NIC-when-every-bit-is-writt.patch +# Patch 482 removed as it has to be discussed and should not be applied yet +# For bz#1005039 - add compat property to disable ctrl_mac_addr feature +Patch483: kvm-don-t-disable-ctrl_mac_addr-feature-for-6.5-machine-.patch +# For bz#848203 - MAC Programming for virtio over macvtap - qemu-kvm support +Patch484: kvm-qapi-qapi-visit.py-fix-list-handling-for-union-types.patch +# For bz#848203 - MAC Programming for virtio over macvtap - qemu-kvm support +Patch485: kvm-qapi-qapi-visit.py-native-list-support.patch +# For bz#848203 - MAC Programming for virtio over macvtap - qemu-kvm support +Patch486: kvm-qapi-enable-generation-of-native-list-code.patch +# For bz#848203 - MAC Programming for virtio over macvtap - qemu-kvm support +Patch487: kvm-net-add-support-of-mac-programming-over-macvtap-in-Q.patch + +BuildRequires: zlib-devel +BuildRequires: SDL-devel +BuildRequires: which +BuildRequires: texi2html +BuildRequires: gnutls-devel +BuildRequires: cyrus-sasl-devel +BuildRequires: libtool +BuildRequires: libaio-devel +BuildRequires: rsync +BuildRequires: pciutils-devel +BuildRequires: pulseaudio-libs-devel +BuildRequires: libiscsi-devel +BuildRequires: ncurses-devel +BuildRequires: libattr-devel +BuildRequires: libusbx-devel +%if 0%{?have_usbredir:1} +BuildRequires: usbredir-devel >= 0.6 +%endif +BuildRequires: texinfo +%if 0%{!?build_only_sub:1} + %if 0%{?have_spice:1} +BuildRequires: spice-protocol >= 0.12.2 +BuildRequires: spice-server-devel >= 0.12.0 + %endif +%endif +%if 0%{?have_seccomp:1} +BuildRequires: libseccomp-devel >= 1.0.0 +%endif +# For network block driver +BuildRequires: libcurl-devel +%if 0%{!?build_only_sub:1} +# For gluster block driver +BuildRequires: glusterfs-api-devel +BuildRequires: glusterfs-devel +%endif +# We need both because the 'stap' binary is probed for by configure +BuildRequires: systemtap +BuildRequires: systemtap-sdt-devel +# For smartcard NSS support +BuildRequires: nss-devel +# For XFS discard support in raw-posix.c +# For VNC JPEG support +BuildRequires: libjpeg-devel +# For VNC PNG support +BuildRequires: libpng-devel +# For uuid generation +BuildRequires: libuuid-devel +# For BlueZ device support +BuildRequires: bluez-libs-devel +# For Braille device support +BuildRequires: brlapi-devel +# For test suite +BuildRequires: check-devel +# For virtfs +BuildRequires: libcap-devel +# Hard requirement for version >= 1.3 +BuildRequires: pixman-devel +# Documentation requirement +BuildRequires: perl-podlators +BuildRequires: texinfo + +%if 0%{!?build_only_sub:1} +Requires: qemu-img = %{epoch}:%{version}-%{release} +%endif + +# RHEV-specific changes: +# We provide special suffix for qemu-kvm so the conflit is easy +# In addition, RHEV version should obsolete all RHEL version in case both +# RHEL and RHEV channels are used +%rhel_rhev_conflicts qemu-kvm + + +%define qemudocdir %{_docdir}/%{pkgname} + +%description +QEMU is a generic and open source processor emulator which achieves a good +emulation speed by using dynamic translation. QEMU has two operating modes: + + * Full system emulation. In this mode, QEMU emulates a full system (for + example a PC), including a processor and various peripherials. It can be + used to launch different Operating Systems without rebooting the PC or + to debug system code. + * User mode emulation. In this mode, QEMU can launch Linux processes compiled + for one CPU on another CPU. + +As QEMU requires no host kernel patches to run, it is safe and easy to use. +%if !%{rhev} +%package -n qemu-img +Summary: QEMU command line tool for manipulating disk images +Group: Development/Tools + +%description -n qemu-img +This package provides a command line tool for manipulating disk images +%endif + +%if 0%{!?build_only_sub:1} +%package -n qemu-kvm-common%{?pkgsuffix} +Summary: QEMU common files needed by all QEMU targets +Group: Development/Tools +Requires(post): /usr/bin/getent +Requires(post): /usr/sbin/groupadd +Requires(post): /usr/sbin/useradd +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units + +%description -n qemu-kvm-common%{?pkgsuffix} +QEMU is a generic and open source processor emulator which achieves a good +emulation speed by using dynamic translation. + +This package provides the common files needed by all QEMU targets + +%rhel_rhev_conflicts qemu-kvm-common +%endif + +%if %{with guest_agent} +%package -n qemu-guest-agent +Summary: QEMU guest agent +Group: System Environment/Daemons +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units + +%description -n qemu-guest-agent +QEMU is a generic and open source processor emulator which achieves a good +emulation speed by using dynamic translation. + +This package provides an agent to run inside guests, which communicates +with the host over a virtio-serial channel named "org.qemu.guest_agent.0" + +This package does not need to be installed on the host OS. + +%post -n qemu-guest-agent +%systemd_post qemu-guest-agent.service + +%preun -n qemu-guest-agent +%systemd_preun qemu-guest-agent.service + +%postun -n qemu-guest-agent +%systemd_postun_with_restart qemu-guest-agent.service + +%endif + +%if !%{rhev} + %if 0%{!?build_only_sub:1} +%package tools +Summary: KVM debugging and diagnostics tools +Group: Development/Tools + +%description tools +This package contains some diagnostics and debugging tools for KVM, +such as kvm_stat. + %endif + +%package -n libcacard +Summary: Common Access Card (CAC) Emulation +Group: Development/Libraries + +%description -n libcacard +Common Access Card (CAC) emulation library. + +%package -n libcacard-tools +Summary: CAC Emulation tools +Group: Development/Libraries +Requires: libcacard = %{epoch}:%{version}-%{release} +# older qemu-img has vscclient which is now in libcacard-tools +Requires: qemu-img >= 3:1.3.0-5 + +%description -n libcacard-tools +CAC emulation tools. + +%package -n libcacard-devel +Summary: CAC Emulation devel +Group: Development/Libraries +Requires: libcacard = %{epoch}:%{version}-%{release} + +%description -n libcacard-devel +CAC emulation development files. +%endif + +%prep +%setup -q -n qemu-%{version} +%patch1 -p1 +#%%patch2 -p1 +#%%patch3 -p1 +#%%patch4 -p1 +#%%patch5 -p1 +#%%patch6 -p1 +#%%patch7 -p1 +#%%patch8 -p1 +#%%patch9 -p1 +#%%patch10 -p1 +#%%patch11 -p1 +#%%patch12 -p1 +#%%patch13 -p1 +#%%patch14 -p1 +#%%patch15 -p1 +#%%patch16 -p1 +#%%patch17 -p1 +#%%patch18 -p1 +#%%patch19 -p1 +#%%patch20 -p1 +#%%patch21 -p1 +#%%patch22 -p1 +#%%patch23 -p1 +#%%patch24 -p1 +#%%patch25 -p1 +#%%patch26 -p1 +#%%patch27 -p1 +#%%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 + +# Fix CPUID model/level values on Conroe/Penryn/Nehalem CPU models +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 + +#%patch41 -p1 +%patch42 -p1 +%patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 +%patch51 -p1 +%patch52 -p1 +%patch53 -p1 +%patch54 -p1 +%patch55 -p1 +%patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +#%%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +#%%patch73 -p1 +%patch74 -p1 +%patch75 -p1 + +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +#%%patch90 -p1 +#%%patch91 -p1 +#%%patch92 -p1 +%patch93 -p1 +%patch94 -p1 +#%%patch95 -p1 +%patch96 -p1 +%patch97 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch119 -p1 +%patch120 -p1 +%patch121 -p1 +%patch122 -p1 +%patch123 -p1 +%patch124 -p1 +%patch125 -p1 +%patch126 -p1 +%patch127 -p1 +%patch128 -p1 +%patch129 -p1 +%patch130 -p1 +%patch131 -p1 +%patch132 -p1 +%patch133 -p1 +%patch134 -p1 +%patch135 -p1 +%patch136 -p1 +%patch137 -p1 +%patch138 -p1 +%patch139 -p1 +%patch140 -p1 +%patch141 -p1 +%patch142 -p1 +%patch143 -p1 +%patch144 -p1 +%patch145 -p1 +%patch146 -p1 +%patch147 -p1 +%patch148 -p1 +%patch149 -p1 +%patch150 -p1 +%patch151 -p1 +%patch152 -p1 +%patch153 -p1 +%patch154 -p1 +%patch155 -p1 +%patch156 -p1 +%patch157 -p1 +%patch158 -p1 +%patch159 -p1 +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch165 -p1 +%patch166 -p1 +%patch168 -p1 +%patch169 -p1 +%patch170 -p1 +%patch171 -p1 +%patch172 -p1 +%patch173 -p1 +%patch174 -p1 +%patch175 -p1 +%patch176 -p1 +%patch177 -p1 +%patch178 -p1 +%patch179 -p1 +%patch180 -p1 +%patch181 -p1 +%patch182 -p1 +%patch183 -p1 +%patch184 -p1 +%patch185 -p1 +%patch186 -p1 +%patch187 -p1 +%patch188 -p1 +%patch189 -p1 +%patch190 -p1 +%patch191 -p1 +%patch192 -p1 +%patch193 -p1 +%patch194 -p1 +%patch195 -p1 +%patch196 -p1 +%patch197 -p1 +%patch198 -p1 +%patch199 -p1 +%patch200 -p1 +%patch201 -p1 +%patch202 -p1 +%patch203 -p1 +%patch204 -p1 +%patch205 -p1 +%patch206 -p1 +%patch207 -p1 +%patch208 -p1 +%patch209 -p1 +%patch210 -p1 +%patch211 -p1 +%patch212 -p1 +%patch213 -p1 +%patch214 -p1 +%patch215 -p1 +%patch216 -p1 +%patch217 -p1 +%patch218 -p1 +%patch219 -p1 +%patch220 -p1 +%patch221 -p1 +%patch222 -p1 +%patch223 -p1 +%patch224 -p1 +%patch225 -p1 +%patch226 -p1 +%patch227 -p1 +%patch228 -p1 +%patch229 -p1 +%patch230 -p1 +%patch231 -p1 +%patch232 -p1 +%patch233 -p1 +%patch234 -p1 +%patch235 -p1 +%patch236 -p1 +%patch237 -p1 +%patch238 -p1 +%patch239 -p1 +%patch240 -p1 +%patch241 -p1 +%patch242 -p1 +%patch243 -p1 +%patch244 -p1 +%patch245 -p1 +%patch246 -p1 +%patch247 -p1 +%patch248 -p1 +%patch249 -p1 +%patch250 -p1 +%patch251 -p1 +%patch252 -p1 +%patch253 -p1 +%patch254 -p1 +%patch255 -p1 +%patch256 -p1 +%patch257 -p1 +%patch258 -p1 +%patch259 -p1 +%patch260 -p1 +%patch261 -p1 +%patch262 -p1 +%patch263 -p1 +%patch264 -p1 +%patch265 -p1 +%patch266 -p1 +%patch267 -p1 +%patch268 -p1 +%patch269 -p1 +%patch270 -p1 +%patch271 -p1 +%patch272 -p1 +%patch273 -p1 +%patch274 -p1 +%patch275 -p1 +%patch276 -p1 +%patch277 -p1 +%patch278 -p1 +%patch279 -p1 +%patch280 -p1 +%patch281 -p1 +%patch282 -p1 +%patch283 -p1 +%patch284 -p1 +%patch285 -p1 +%patch286 -p1 +%patch287 -p1 +%patch288 -p1 +%patch289 -p1 +%patch290 -p1 +%patch291 -p1 +%patch292 -p1 +%patch293 -p1 +%patch294 -p1 +%patch295 -p1 +%patch296 -p1 +%patch297 -p1 +%patch298 -p1 +%patch299 -p1 +%patch300 -p1 +%patch301 -p1 +%patch302 -p1 +%patch303 -p1 +%patch304 -p1 +%patch305 -p1 +%patch306 -p1 +%patch307 -p1 +%patch308 -p1 +%patch309 -p1 +%patch310 -p1 +%patch311 -p1 +%patch312 -p1 +%patch313 -p1 +%patch314 -p1 +%patch315 -p1 +%patch316 -p1 +%patch317 -p1 +%patch318 -p1 +%patch319 -p1 +%patch320 -p1 +%patch321 -p1 +%patch322 -p1 +%patch323 -p1 +%patch324 -p1 +%patch325 -p1 +%patch326 -p1 +%patch327 -p1 +%patch328 -p1 +%patch329 -p1 +%patch330 -p1 +%patch331 -p1 +%patch332 -p1 +%patch333 -p1 +%patch334 -p1 +%patch335 -p1 +%patch336 -p1 +%patch337 -p1 +%patch338 -p1 +%patch339 -p1 +%patch340 -p1 +%patch341 -p1 +%patch342 -p1 +%patch343 -p1 +%patch344 -p1 +%patch345 -p1 +%patch346 -p1 +%patch347 -p1 +%patch348 -p1 +%patch349 -p1 +%patch350 -p1 +%patch351 -p1 +%patch352 -p1 +%patch353 -p1 +%patch354 -p1 +%patch355 -p1 +%patch356 -p1 +%patch357 -p1 +%patch358 -p1 +%patch359 -p1 +%patch360 -p1 +%patch361 -p1 +%patch362 -p1 +%patch363 -p1 +%patch364 -p1 +%patch365 -p1 +%patch366 -p1 +%patch367 -p1 +%patch368 -p1 +%patch369 -p1 +%patch370 -p1 +%patch371 -p1 +%patch372 -p1 +%patch373 -p1 +%patch374 -p1 +%patch375 -p1 +%patch376 -p1 +%patch377 -p1 +%patch378 -p1 +%patch379 -p1 +%patch380 -p1 +%patch381 -p1 +%patch382 -p1 +%patch383 -p1 +%patch384 -p1 +%patch385 -p1 +%patch386 -p1 +%patch387 -p1 +%patch388 -p1 +%patch389 -p1 +%patch390 -p1 +%patch391 -p1 +%patch392 -p1 +%patch393 -p1 +%patch394 -p1 +%patch395 -p1 +%patch396 -p1 +%patch397 -p1 +%patch398 -p1 +%patch399 -p1 +%patch400 -p1 +%patch401 -p1 +%patch402 -p1 +%patch403 -p1 +%patch404 -p1 +%patch405 -p1 +%patch406 -p1 +%patch407 -p1 +%patch408 -p1 +%patch409 -p1 +%patch410 -p1 +%patch411 -p1 +%patch412 -p1 +%patch413 -p1 +%patch414 -p1 +%patch415 -p1 +%patch416 -p1 +%patch417 -p1 +%patch418 -p1 +%patch419 -p1 +%patch420 -p1 +%patch421 -p1 +%patch422 -p1 +%patch423 -p1 +%patch424 -p1 +%patch425 -p1 +%patch426 -p1 +%patch427 -p1 +%patch428 -p1 +%patch429 -p1 +%patch430 -p1 +%patch431 -p1 +%patch432 -p1 +%patch433 -p1 +%patch434 -p1 +%patch435 -p1 +%patch436 -p1 +%patch437 -p1 +%patch438 -p1 +%patch439 -p1 +%patch440 -p1 +%patch441 -p1 +%patch442 -p1 +%patch443 -p1 +%patch444 -p1 +%patch445 -p1 +%patch446 -p1 +%patch447 -p1 +%patch448 -p1 +%patch449 -p1 +%patch450 -p1 +%patch451 -p1 +%patch452 -p1 +%patch453 -p1 +%patch454 -p1 +%patch455 -p1 +%patch456 -p1 +%patch457 -p1 +%patch458 -p1 +%patch459 -p1 +%patch460 -p1 +%patch461 -p1 +%patch462 -p1 +%patch463 -p1 +%patch464 -p1 +%patch465 -p1 +%patch466 -p1 +%patch467 -p1 +%patch468 -p1 +%patch469 -p1 +%patch470 -p1 +%patch471 -p1 +%patch472 -p1 +%patch473 -p1 +%patch474 -p1 +%patch475 -p1 +%patch476 -p1 +%patch477 -p1 +%patch478 -p1 +%patch479 -p1 +%patch480 -p1 +%patch481 -p1 +#%patch482 -p1 +%patch483 -p1 +%patch484 -p1 +%patch485 -p1 +%patch486 -p1 +%patch487 -p1 + +%build +buildarch="%{kvm_target}-softmmu" + +# --build-id option is used for giving info to the debug packages. +extraldflags="-Wl,--build-id"; +buildldflags="VL_LDFLAGS=-Wl,--build-id" + +%ifarch s390 + # drop -g flag to prevent memory exhaustion by linker + %global optflags %(echo %{optflags} | sed 's/-g//') + sed -i.debug 's/"-g $CFLAGS"/"$CFLAGS"/g' configure +%endif + +dobuild() { +%if 0%{!?build_only_sub:1} + ./configure \ + --prefix=%{_prefix} \ + --libdir=%{_libdir} \ + --sysconfdir=%{_sysconfdir} \ + --interp-prefix=%{_prefix}/qemu-%%M \ + --audio-drv-list=pa,alsa \ + --with-confsuffix=/%{pkgname} \ + --localstatedir=%{_localstatedir} \ + --libexecdir=%{_libexecdir} \ + --with-pkgversion=%{pkgname}-%{version}-%{release} \ + --disable-strip \ + --extra-ldflags="$extraldflags -pie -Wl,-z,relro -Wl,-z,now" \ + --extra-cflags="%{optflags} -fPIE -DPIE" \ + --enable-trace-backend=dtrace \ + --enable-werror \ + --disable-xen \ + --disable-virtfs \ + --enable-kvm \ + --enable-libusb \ + --enable-spice \ + --enable-seccomp \ + --disable-fdt \ + --enable-docs \ + --disable-sdl \ + --disable-debug-tcg \ + --disable-sparse \ + --disable-brlapi \ + --disable-bluez \ + --disable-vde \ + --disable-curses \ + --disable-curl \ + --enable-vnc-tls \ + --enable-vnc-sasl \ + --enable-linux-aio \ + --enable-smartcard-nss \ + --enable-usb-redir \ + --enable-vnc-png \ + --disable-vnc-jpeg \ + --enable-vnc-ws \ + --enable-uuid \ + --disable-vhost-scsi \ +%if %{with guest_agent} + --enable-guest-agent \ +%else + --disable-guest-agent \ +%endif +%if %{rhev} + --enable-live-block-ops \ + --enable-ceph-support \ +%else + --disable-live-block-ops \ + --disable-ceph-support \ +%endif + --disable-live-block-migration \ + --enable-glusterfs \ +%if %{rhev} + --block-drv-rw-whitelist=qcow2,raw,file,host_device,nbd,iscsi,gluster,rbd \ +%else + --block-drv-rw-whitelist=qcow2,raw,file,host_device,nbd,iscsi,gluster \ +%endif + --block-drv-ro-whitelist=vmdk,vhdx,vpc \ + "$@" + + echo "config-host.mak contents:" + echo "===" + cat config-host.mak + echo "===" + + make V=1 %{?_smp_mflags} $buildldflags +%else + ./configure --prefix=%{_prefix} \ + --libdir=%{_libdir} \ + --with-pkgversion=%{pkgname}-%{version}-%{release} \ + --disable-guest-agent \ + --target-list= --cpu=%{_arch} + + make libcacard.la %{?_smp_mflags} $buildldflags + make vscclient %{?_smp_mflags} $buildldflags + make qemu-img %{?_smp_mflags} $buildldflags + make qemu-io %{?_smp_mflags} $buildldflags + make qemu-nbd %{?_smp_mflags} $buildldflags + make qemu-img.1 %{?_smp_mflags} $buildldflags + make qemu-nbd.8 %{?_smp_mflags} $buildldflags + make qemu-ga %{?_smp_mflags} $buildldflags +%endif +} + +dobuild --target-list="$buildarch" + +%if 0%{!?build_only_sub:1} + # Setup back compat qemu-kvm binary + ./scripts/tracetool.py --backend dtrace --format stap \ + --binary %{_libexecdir}/qemu-kvm --target-arch %{kvm_target} \ + --target-type system --probe-prefix \ + qemu.kvm < ./trace-events > qemu-kvm.stp + + cp -a %{kvm_target}-softmmu/qemu-system-%{kvm_target} qemu-kvm + + + gcc %{SOURCE6} -O2 -g -o ksmctl +%endif + +%install +%define _udevdir %(pkg-config --variable=udevdir udev)/rules.d + +%if 0%{!?build_only_sub:1} + install -D -p -m 0644 %{SOURCE4} $RPM_BUILD_ROOT%{_libdir}/systemd/system/ksm.service + install -D -p -m 0644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/ksm + install -D -p -m 0755 ksmctl $RPM_BUILD_ROOT%{_libdir}/systemd/ksmctl + + install -D -p -m 0644 %{SOURCE7} $RPM_BUILD_ROOT%{_libdir}/systemd/system/ksmtuned.service + install -D -p -m 0755 %{SOURCE8} $RPM_BUILD_ROOT%{_sbindir}/ksmtuned + install -D -p -m 0644 %{SOURCE9} $RPM_BUILD_ROOT%{_sysconfdir}/ksmtuned.conf + + mkdir -p $RPM_BUILD_ROOT%{_bindir}/ + mkdir -p $RPM_BUILD_ROOT%{_udevdir} + + install -m 0755 scripts/kvm/kvm_stat $RPM_BUILD_ROOT%{_bindir}/ + install -m 0644 %{SOURCE3} $RPM_BUILD_ROOT%{_udevdir} + + 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 + install %{SOURCE14} $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/ + install %{SOURCE15} $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/ + install %{SOURCE16} $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/ + install %{SOURCE17} $RPM_BUILD_ROOT%{_datadir}/%{pkgname}/ + + install -m 0755 qemu-kvm $RPM_BUILD_ROOT%{_libexecdir}/ + install -m 0644 qemu-kvm.stp $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/ + + rm $RPM_BUILD_ROOT%{_bindir}/qemu-system-%{kvm_target} + rm $RPM_BUILD_ROOT%{_datadir}/systemtap/tapset/qemu-system-%{kvm_target}.stp + + mkdir -p $RPM_BUILD_ROOT%{qemudocdir} + install -p -m 0644 -t ${RPM_BUILD_ROOT}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE + 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} + chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man1/* + chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man8/* + + install -D -p -m 0644 qemu.sasl $RPM_BUILD_ROOT%{_sysconfdir}/sasl2/qemu-kvm.conf + + # Provided by package openbios + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/openbios-ppc + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/openbios-sparc32 + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/openbios-sparc64 + # Provided by package SLOF + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/slof.bin + + # Remove unpackaged files. + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/palcode-clipper + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/petalogix*.dtb + rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/bamboo.dtb + rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/ppc_rom.bin + rm -f ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/spapr-rtas.bin + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/s390-zipl.rom + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/s390-ccw.img + + # Remove efi roms + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/efi*.rom + + # Provided by package ipxe + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/pxe*rom + # Provided by package vgabios + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/vgabios*bin + # Provided by package seabios + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/bios.bin + # Provided by package sgabios + rm -rf ${RPM_BUILD_ROOT}%{_datadir}/%{pkgname}/sgabios.bin + + # the pxe gpxe images will be symlinks to the images on + # /usr/share/ipxe, as QEMU doesn't know how to look + # for other paths, yet. + pxe_link() { + ln -s ../ipxe/$2.rom %{buildroot}%{_datadir}/%{pkgname}/pxe-$1.rom + } + + pxe_link e1000 8086100e + pxe_link ne2k_pci 10ec8029 + pxe_link pcnet 10222000 + pxe_link rtl8139 10ec8139 + pxe_link virtio 1af41000 + + rom_link() { + ln -s $1 %{buildroot}%{_datadir}/%{pkgname}/$2 + } + + rom_link ../seavgabios/vgabios-isavga.bin vgabios.bin + rom_link ../seavgabios/vgabios-cirrus.bin vgabios-cirrus.bin + rom_link ../seavgabios/vgabios-qxl.bin vgabios-qxl.bin + rom_link ../seavgabios/vgabios-stdvga.bin vgabios-stdvga.bin + rom_link ../seavgabios/vgabios-vmware.bin vgabios-vmware.bin + rom_link ../seabios/bios.bin bios.bin + rom_link ../sgabios/sgabios.bin sgabios.bin +%endif + +%if %{with guest_agent} + # For the qemu-guest-agent subpackage, install: + # - the systemd service file and the udev rules: + mkdir -p $RPM_BUILD_ROOT%{_unitdir} + mkdir -p $RPM_BUILD_ROOT%{_udevdir} + install -m 0644 %{SOURCE10} $RPM_BUILD_ROOT%{_unitdir} + install -m 0644 %{SOURCE11} $RPM_BUILD_ROOT%{_udevdir} + + # - the environment file for the systemd service: + install -D -p -m 0644 %{SOURCE13} \ + $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/qemu-ga + + # - the fsfreeze hook script: + install -D --preserve-timestamps \ + scripts/qemu-guest-agent/fsfreeze-hook \ + $RPM_BUILD_ROOT%{_sysconfdir}/qemu-ga/fsfreeze-hook + + # - the directory for user scripts: + mkdir $RPM_BUILD_ROOT%{_sysconfdir}/qemu-ga/fsfreeze-hook.d + + # - and the fsfreeze script samples: + mkdir --parents $RPM_BUILD_ROOT%{_datadir}/%{name}/qemu-ga/fsfreeze-hook.d/ + install --preserve-timestamps --mode=0644 \ + scripts/qemu-guest-agent/fsfreeze-hook.d/*.sample \ + $RPM_BUILD_ROOT%{_datadir}/%{name}/qemu-ga/fsfreeze-hook.d/ + + # - Install dedicated log directory: + mkdir -p -v $RPM_BUILD_ROOT%{_localstatedir}/log/qemu-ga/ +%endif + +%if 0%{!?build_only_sub:1} + # Install rules to use the bridge helper with libvirt's virbr0 + install -m 0644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/%{pkgname} + chmod u+s $RPM_BUILD_ROOT%{_libexecdir}/qemu-bridge-helper +%endif + +%if !%{rhev} + make %{?_smp_mflags} $buildldflags DESTDIR=$RPM_BUILD_ROOT install-libcacard + find $RPM_BUILD_ROOT -name "libcacard.so*" -exec chmod +x \{\} \; +%endif +find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f + +%if 0%{?build_only_sub} + mkdir -p $RPM_BUILD_ROOT%{_bindir} + mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1/* + mkdir -p $RPM_BUILD_ROOT%{_mandir}/man8/* + libtool --mode=install install -m 0755 vscclient $RPM_BUILD_ROOT%{_bindir}/vscclient + install -m 0755 qemu-img $RPM_BUILD_ROOT%{_bindir}/qemu-img + install -m 0755 qemu-io $RPM_BUILD_ROOT%{_bindir}/qemu-io + install -m 0755 qemu-nbd $RPM_BUILD_ROOT%{_bindir}/qemu-nbd + install -c -m 0644 qemu-img.1 ${RPM_BUILD_ROOT}%{_mandir}/man1/qemu-img.1 + install -c -m 0644 qemu-nbd.8 ${RPM_BUILD_ROOT}%{_mandir}/man8/qemu-nbd.8 + install -c -m 0755 qemu-ga ${RPM_BUILD_ROOT}%{_bindir}/qemu-ga + chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man1/* + chmod -x ${RPM_BUILD_ROOT}%{_mandir}/man8/* +%endif + +%if %{rhev} + # Remove files unpackacked for rhev build + rm -rf ${RPM_BUILD_ROOT}%{_includedir}/cacard + rm -rf ${RPM_BUILD_ROOT}%{_bindir}/qemu-img + rm -rf ${RPM_BUILD_ROOT}%{_bindir}/qemu-io + rm -rf ${RPM_BUILD_ROOT}%{_bindir}/qemu-nbd + rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man1/qemu-img.1* + rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man8/qemu-nbd.8* + rm -rf ${RPM_BUILD_ROOT}%{_bindir}/vscclient + rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcacard.so* + rm -rf ${RPM_BUILD_ROOT}%{_libdir}/pkgconfig/libcacard.pc + rm -rf ${RPM_BUILD_ROOT}%{_bindir}/kvm_stat +%endif + +%if 0%{!?build_only_sub:1} +%check + make check +%endif +%post +# load kvm modules now, so we can make sure no reboot is needed. +# If there's already a kvm module installed, we don't mess with it +sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : + udevadm trigger --subsystem-match=misc --sysname-match=kvm --action=add || : + +%if 0%{!?build_only_sub:1} +%post -n qemu-kvm-common%{?pkgsuffix} + %systemd_post ksm.service + %systemd_post ksmtuned.service + + getent group kvm >/dev/null || groupadd -g 36 -r kvm + getent group qemu >/dev/null || groupadd -g 107 -r qemu + getent passwd qemu >/dev/null || \ + useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ + -c "qemu user" qemu + +%preun -n qemu-kvm-common%{?pkgsuffix} + %systemd_preun ksm.service + %systemd_preun ksmtuned.service + +%postun -n qemu-kvm-common%{?pkgsuffix} + %systemd_postun_with_restart ksm.service + %systemd_postun_with_restart ksmtuned.service +%endif + +%global kvm_files \ +%{_udevdir}/80-kvm.rules + +%global qemu_kvm_files \ +%{_libexecdir}/qemu-kvm \ +%{_datadir}/systemtap/tapset/qemu-kvm.stp + +%if 0%{!?build_only_sub:1} +%files -n qemu-kvm-common%{?pkgsuffix} + %defattr(-,root,root) + %dir %{qemudocdir} + %doc %{qemudocdir}/Changelog + %doc %{qemudocdir}/README + %doc %{qemudocdir}/qemu-doc.html + %doc %{qemudocdir}/qemu-tech.html + %doc %{qemudocdir}/qmp-commands.txt + %doc %{qemudocdir}/COPYING + %doc %{qemudocdir}/COPYING.LIB + %doc %{qemudocdir}/LICENSE + %dir %{_datadir}/%{pkgname}/ + %{_datadir}/%{pkgname}/keymaps/ + %{_mandir}/man1/%{pkgname}.1* + %attr(4755, -, -) %{_libexecdir}/qemu-bridge-helper + %config(noreplace) %{_sysconfdir}/sasl2/%{pkgname}.conf + %{_libdir}/systemd/system/ksm.service + %{_libdir}/systemd/ksmctl + %config(noreplace) %{_sysconfdir}/sysconfig/ksm + %{_libdir}/systemd/system/ksmtuned.service + %{_sbindir}/ksmtuned + %config(noreplace) %{_sysconfdir}/ksmtuned.conf + %dir %{_sysconfdir}/%{pkgname} + %config(noreplace) %{_sysconfdir}/%{pkgname}/bridge.conf +%endif + +%if %{with guest_agent} +%files -n qemu-guest-agent + %defattr(-,root,root,-) + %doc COPYING README + %{_bindir}/qemu-ga + %{_unitdir}/qemu-guest-agent.service + %{_udevdir}/99-qemu-guest-agent.rules + %{_sysconfdir}/sysconfig/qemu-ga + %{_sysconfdir}/qemu-ga + %{_datadir}/%{name}/qemu-ga + %dir %{_localstatedir}/log/qemu-ga +%endif + +%if 0%{!?build_only_sub:1} +%files + %defattr(-,root,root) + %{_datadir}/%{pkgname}/acpi-dsdt.aml + %{_datadir}/%{pkgname}/q35-acpi-dsdt.aml + %{_datadir}/%{pkgname}/bios.bin + %{_datadir}/%{pkgname}/sgabios.bin + %{_datadir}/%{pkgname}/linuxboot.bin + %{_datadir}/%{pkgname}/multiboot.bin + %{_datadir}/%{pkgname}/kvmvapic.bin + %{_datadir}/%{pkgname}/vgabios.bin + %{_datadir}/%{pkgname}/vgabios-cirrus.bin + %{_datadir}/%{pkgname}/vgabios-qxl.bin + %{_datadir}/%{pkgname}/vgabios-stdvga.bin + %{_datadir}/%{pkgname}/vgabios-vmware.bin + %{_datadir}/%{pkgname}/pxe-e1000.rom + %{_datadir}/%{pkgname}/pxe-virtio.rom + %{_datadir}/%{pkgname}/pxe-pcnet.rom + %{_datadir}/%{pkgname}/pxe-rtl8139.rom + %{_datadir}/%{pkgname}/pxe-ne2k_pci.rom + %{_datadir}/%{pkgname}/qemu-icon.bmp + %{_datadir}/%{pkgname}/rhel6-virtio.rom + %{_datadir}/%{pkgname}/rhel6-pcnet.rom + %{_datadir}/%{pkgname}/rhel6-rtl8139.rom + %{_datadir}/%{pkgname}/rhel6-ne2k_pci.rom + %config(noreplace) %{_sysconfdir}/%{pkgname}/target-x86_64.conf + %{?kvm_files:} + %{?qemu_kvm_files:} + + %if !%{rhev} +%files tools + %defattr(-,root,root,-) + %{_bindir}/kvm_stat + %endif +%endif + +%if !%{rhev} +%files -n qemu-img + %defattr(-,root,root) + %{_bindir}/qemu-img + %{_bindir}/qemu-io + %{_bindir}/qemu-nbd + %{_mandir}/man1/qemu-img.1* + %{_mandir}/man8/qemu-nbd.8* + +%files -n libcacard + %defattr(-,root,root,-) + %{_libdir}/libcacard.so.* + +%files -n libcacard-tools + %defattr(-,root,root,-) + %{_bindir}/vscclient + +%files -n libcacard-devel + %defattr(-,root,root,-) + %{_includedir}/cacard + %{_libdir}/libcacard.so + %{_libdir}/pkgconfig/libcacard.pc +%endif + +%changelog +* Mon Nov 11 2013 Miroslav Rezanina - 1.5.3-19.el7 +- kvm-qapi-qapi-visit.py-fix-list-handling-for-union-types.patch [bz#848203] +- kvm-qapi-qapi-visit.py-native-list-support.patch [bz#848203] +- kvm-qapi-enable-generation-of-native-list-code.patch [bz#848203] +- kvm-net-add-support-of-mac-programming-over-macvtap-in-Q.patch [bz#848203] +- Resolves: bz#848203 + (MAC Programming for virtio over macvtap - qemu-kvm support) + +* Fri Nov 08 2013 Michal Novotny - 1.5.3-18.el7 +- Removing leaked patch kvm-e1000-rtl8139-update-HMP-NIC-when-every-bit-is-writt.patch + +* Thu Nov 07 2013 Miroslav Rezanina - 1.5.3-17.el7 +- kvm-pci-assign-Add-MSI-affinity-support.patch [bz#1025877] +- kvm-Fix-potential-resource-leak-missing-fclose.patch [bz#1025877] +- kvm-pci-assign-remove-the-duplicate-function-name-in-deb.patch [bz#1025877] +- kvm-Remove-s390-ccw-img-loader.patch [bz#1017682] +- kvm-Fix-vscclient-installation.patch [bz#1017681] +- kvm-Change-qemu-bridge-helper-permissions-to-4755.patch [bz#1017689] +- kvm-net-update-nic-info-during-device-reset.patch [bz#922589] +- kvm-net-e1000-update-network-information-when-macaddr-is.patch [bz#922589] +- kvm-net-rtl8139-update-network-information-when-macaddr-.patch [bz#922589] +- kvm-virtio-net-fix-up-HMP-NIC-info-string-on-reset.patch [bz#1026689] +- kvm-vfio-pci-VGA-quirk-update.patch [bz#1025477] +- kvm-vfio-pci-Add-support-for-MSI-affinity.patch [bz#1025477] +- kvm-vfio-pci-Test-device-reset-capabilities.patch [bz#1026550] +- kvm-vfio-pci-Lazy-PCI-option-ROM-loading.patch [bz#1026550] +- kvm-vfio-pci-Cleanup-error_reports.patch [bz#1026550] +- kvm-vfio-pci-Add-dummy-PCI-ROM-write-accessor.patch [bz#1026550] +- kvm-vfio-pci-Fix-endian-issues-in-vfio_pci_size_rom.patch [bz#1026550] +- kvm-linux-headers-Update-to-include-vfio-pci-hot-reset-s.patch [bz#1025472] +- kvm-vfio-pci-Implement-PCI-hot-reset.patch [bz#1025472] +- kvm-linux-headers-Update-for-KVM-VFIO-device.patch [bz#1025474] +- kvm-vfio-pci-Make-use-of-new-KVM-VFIO-device.patch [bz#1025474] +- kvm-vmdk-Fix-vmdk_parse_extents.patch [bz#995866] +- kvm-vmdk-fix-VMFS-extent-parsing.patch [bz#995866] +- kvm-e1000-rtl8139-update-HMP-NIC-when-every-bit-is-writt.patch [bz#922589] +- kvm-don-t-disable-ctrl_mac_addr-feature-for-6.5-machine-.patch [bz#1005039] +- Resolves: bz#1005039 + (add compat property to disable ctrl_mac_addr feature) +- Resolves: bz#1017681 + (rpmdiff test "Multilib regressions": vscclient is a libtool script on s390/s390x/ppc/ppc64) +- Resolves: bz#1017682 + (/usr/share/qemu-kvm/s390-ccw.img need not be distributed) +- Resolves: bz#1017689 + (/usr/libexec/qemu-bridge-helper permissions should be 4755) +- Resolves: bz#1025472 + (Nvidia GPU device assignment - qemu-kvm - bus reset support) +- Resolves: bz#1025474 + (Nvidia GPU device assignment - qemu-kvm - NoSnoop support) +- Resolves: bz#1025477 + (VFIO MSI affinity) +- Resolves: bz#1025877 + (pci-assign lacks MSI affinity support) +- Resolves: bz#1026550 + (QEMU VFIO update ROM loading code) +- Resolves: bz#1026689 + (virtio-net: macaddr is reset but network info of monitor isn't updated) +- Resolves: bz#922589 + (e1000/rtl8139: qemu mac address can not be changed via set the hardware address in guest) +- Resolves: bz#995866 + (fix vmdk support to ESX images) + +* Thu Nov 07 2013 Miroslav Rezanina - 1.5.3-16.el7 +- kvm-block-drop-bs_snapshots-global-variable.patch [bz#1026524] +- kvm-block-move-snapshot-code-in-block.c-to-block-snapsho.patch [bz#1026524] +- kvm-block-fix-vvfat-error-path-for-enable_write_target.patch [bz#1026524] +- kvm-block-Bugfix-format-and-snapshot-used-in-drive-optio.patch [bz#1026524] +- kvm-iscsi-use-bdrv_new-instead-of-stack-structure.patch [bz#1026524] +- kvm-qcow2-Add-corrupt-bit.patch [bz#1004347] +- kvm-qcow2-Metadata-overlap-checks.patch [bz#1004347] +- kvm-qcow2-Employ-metadata-overlap-checks.patch [bz#1004347] +- kvm-qcow2-refcount-Move-OFLAG_COPIED-checks.patch [bz#1004347] +- kvm-qcow2-refcount-Repair-OFLAG_COPIED-errors.patch [bz#1004347] +- kvm-qcow2-refcount-Repair-shared-refcount-blocks.patch [bz#1004347] +- kvm-qcow2_check-Mark-image-consistent.patch [bz#1004347] +- kvm-qemu-iotests-Overlapping-cluster-allocations.patch [bz#1004347] +- kvm-w32-Fix-access-to-host-devices-regression.patch [bz#1026524] +- kvm-add-qemu-img-convert-n-option-skip-target-volume-cre.patch [bz#1026524] +- kvm-bdrv-Use-Error-for-opening-images.patch [bz#1026524] +- kvm-bdrv-Use-Error-for-creating-images.patch [bz#1026524] +- kvm-block-Error-parameter-for-open-functions.patch [bz#1026524] +- kvm-block-Error-parameter-for-create-functions.patch [bz#1026524] +- kvm-qemu-img-create-Emit-filename-on-error.patch [bz#1026524] +- kvm-qcow2-Use-Error-parameter.patch [bz#1026524] +- kvm-qemu-iotests-Adjustments-due-to-error-propagation.patch [bz#1026524] +- kvm-block-raw-Employ-error-parameter.patch [bz#1026524] +- kvm-block-raw-win32-Employ-error-parameter.patch [bz#1026524] +- kvm-blkdebug-Employ-error-parameter.patch [bz#1026524] +- kvm-blkverify-Employ-error-parameter.patch [bz#1026524] +- kvm-block-raw-posix-Employ-error-parameter.patch [bz#1026524] +- kvm-block-raw-win32-Always-use-errno-in-hdev_open.patch [bz#1026524] +- kvm-qmp-Documentation-for-BLOCK_IMAGE_CORRUPTED.patch [bz#1004347] +- kvm-qcow2-Correct-snapshots-size-for-overlap-check.patch [bz#1004347] +- kvm-qcow2-CHECK_OFLAG_COPIED-is-obsolete.patch [bz#1004347] +- kvm-qcow2-Correct-endianness-in-overlap-check.patch [bz#1004347] +- kvm-qcow2-Switch-L1-table-in-a-single-sequence.patch [bz#1004347] +- kvm-qcow2-Use-pread-for-inactive-L1-in-overlap-check.patch [bz#1004347] +- kvm-qcow2-Remove-wrong-metadata-overlap-check.patch [bz#1004347] +- kvm-qcow2-Use-negated-overflow-check-mask.patch [bz#1004347] +- kvm-qcow2-Make-overlap-check-mask-variable.patch [bz#1004347] +- kvm-qcow2-Add-overlap-check-options.patch [bz#1004347] +- kvm-qcow2-Array-assigning-options-to-OL-check-bits.patch [bz#1004347] +- kvm-qcow2-Add-more-overlap-check-bitmask-macros.patch [bz#1004347] +- kvm-qcow2-Evaluate-overlap-check-options.patch [bz#1004347] +- kvm-qapi-types.py-Split-off-generate_struct_fields.patch [bz#978402] +- kvm-qapi-types.py-Fix-enum-struct-sizes-on-i686.patch [bz#978402] +- kvm-qapi-types-visit.py-Pass-whole-expr-dict-for-structs.patch [bz#978402] +- kvm-qapi-types-visit.py-Inheritance-for-structs.patch [bz#978402] +- kvm-blockdev-Introduce-DriveInfo.enable_auto_del.patch [bz#978402] +- kvm-Implement-qdict_flatten.patch [bz#978402] +- kvm-blockdev-blockdev-add-QMP-command.patch [bz#978402] +- kvm-blockdev-Separate-ID-generation-from-DriveInfo-creat.patch [bz#978402] +- kvm-blockdev-Pass-QDict-to-blockdev_init.patch [bz#978402] +- kvm-blockdev-Move-parsing-of-media-option-to-drive_init.patch [bz#978402] +- kvm-blockdev-Move-parsing-of-if-option-to-drive_init.patch [bz#978402] +- kvm-blockdev-Moving-parsing-of-geometry-options-to-drive.patch [bz#978402] +- kvm-blockdev-Move-parsing-of-boot-option-to-drive_init.patch [bz#978402] +- kvm-blockdev-Move-bus-unit-index-processing-to-drive_ini.patch [bz#978402] +- kvm-blockdev-Move-virtio-blk-device-creation-to-drive_in.patch [bz#978402] +- kvm-blockdev-Remove-IF_-check-for-read-only-blockdev_ini.patch [bz#978402] +- kvm-qemu-iotests-Check-autodel-behaviour-for-device_del.patch [bz#978402] +- kvm-blockdev-Remove-media-parameter-from-blockdev_init.patch [bz#978402] +- kvm-blockdev-Don-t-disable-COR-automatically-with-blockd.patch [bz#978402] +- kvm-blockdev-blockdev_init-error-conversion.patch [bz#978402] +- kvm-sd-Avoid-access-to-NULL-BlockDriverState.patch [bz#978402] +- kvm-blockdev-fix-cdrom-read_only-flag.patch [bz#978402] +- kvm-block-fix-backing-file-overriding.patch [bz#978402] +- kvm-block-Disable-BDRV_O_COPY_ON_READ-for-the-backing-fi.patch [bz#978402] +- kvm-block-Don-t-copy-backing-file-name-on-error.patch [bz#978402] +- kvm-qemu-iotests-Try-creating-huge-qcow2-image.patch [bz#980771] +- kvm-block-move-qmp-and-info-dump-related-code-to-block-q.patch [bz#980771] +- kvm-block-dump-snapshot-and-image-info-to-specified-outp.patch [bz#980771] +- kvm-block-add-snapshot-info-query-function-bdrv_query_sn.patch [bz#980771] +- kvm-block-add-image-info-query-function-bdrv_query_image.patch [bz#980771] +- kvm-qmp-add-ImageInfo-in-BlockDeviceInfo-used-by-query-b.patch [bz#980771] +- kvm-vmdk-Implement-.bdrv_has_zero_init.patch [bz#980771] +- kvm-qemu-iotests-Add-basic-ability-to-use-binary-sample-.patch [bz#980771] +- kvm-qemu-iotests-Quote-TEST_IMG-and-TEST_DIR-usage.patch [bz#980771] +- kvm-qemu-iotests-fix-test-case-059.patch [bz#980771] +- kvm-qapi-Add-ImageInfoSpecific-type.patch [bz#980771] +- kvm-block-Add-bdrv_get_specific_info.patch [bz#980771] +- kvm-block-qapi-Human-readable-ImageInfoSpecific-dump.patch [bz#980771] +- kvm-qcow2-Add-support-for-ImageInfoSpecific.patch [bz#980771] +- kvm-qemu-iotests-Discard-specific-info-in-_img_info.patch [bz#980771] +- kvm-qemu-iotests-Additional-info-from-qemu-img-info.patch [bz#980771] +- kvm-vmdk-convert-error-code-to-use-errp.patch [bz#980771] +- kvm-vmdk-refuse-enabling-zeroed-grain-with-flat-images.patch [bz#980771] +- kvm-qapi-Add-optional-field-compressed-to-ImageInfo.patch [bz#980771] +- kvm-vmdk-Only-read-cid-from-image-file-when-opening.patch [bz#980771] +- kvm-vmdk-Implment-bdrv_get_specific_info.patch [bz#980771] +- Resolves: bz#1004347 + (Backport qcow2 corruption prevention patches) +- Resolves: bz#1026524 + (Backport block layer error parameter patches) +- Resolves: bz#978402 + ([RFE] Add discard support to qemu-kvm layer) +- Resolves: bz#980771 + ([RFE] qemu-img should be able to tell the compat version of a qcow2 image) + +* Thu Nov 07 2013 Miroslav Rezanina - 1.5.3-15.el7 +- kvm-cow-make-reads-go-at-a-decent-speed.patch [bz#989646] +- kvm-cow-make-writes-go-at-a-less-indecent-speed.patch [bz#989646] +- kvm-cow-do-not-call-bdrv_co_is_allocated.patch [bz#989646] +- kvm-block-keep-bs-total_sectors-up-to-date-even-for-grow.patch [bz#989646] +- kvm-block-make-bdrv_co_is_allocated-static.patch [bz#989646] +- kvm-block-do-not-use-total_sectors-in-bdrv_co_is_allocat.patch [bz#989646] +- kvm-block-remove-bdrv_is_allocated_above-bdrv_co_is_allo.patch [bz#989646] +- kvm-block-expect-errors-from-bdrv_co_is_allocated.patch [bz#989646] +- kvm-block-Fix-compiler-warning-Werror-uninitialized.patch [bz#989646] +- kvm-qemu-img-always-probe-the-input-image-for-allocated-.patch [bz#989646] +- kvm-block-make-bdrv_has_zero_init-return-false-for-copy-.patch [bz#989646] +- kvm-block-introduce-bdrv_get_block_status-API.patch [bz#989646] +- kvm-block-define-get_block_status-return-value.patch [bz#989646] +- kvm-block-return-get_block_status-data-and-flags-for-for.patch [bz#989646] +- kvm-block-use-bdrv_has_zero_init-to-return-BDRV_BLOCK_ZE.patch [bz#989646] +- kvm-block-return-BDRV_BLOCK_ZERO-past-end-of-backing-fil.patch [bz#989646] +- kvm-qemu-img-add-a-map-subcommand.patch [bz#989646] +- kvm-docs-qapi-document-qemu-img-map.patch [bz#989646] +- kvm-raw-posix-return-get_block_status-data-and-flags.patch [bz#989646] +- kvm-raw-posix-report-unwritten-extents-as-zero.patch [bz#989646] +- kvm-block-add-default-get_block_status-implementation-fo.patch [bz#989646] +- kvm-block-look-for-zero-blocks-in-bs-file.patch [bz#989646] +- kvm-qemu-img-fix-invalid-JSON.patch [bz#989646] +- kvm-block-get_block_status-set-pnum-0-on-error.patch [bz#989646] +- kvm-block-get_block_status-avoid-segfault-if-there-is-no.patch [bz#989646] +- kvm-block-get_block_status-avoid-redundant-callouts-on-r.patch [bz#989646] +- kvm-qcow2-Restore-total_sectors-value-in-save_vmstate.patch [bz#1025740] +- kvm-qcow2-Unset-zero_beyond_eof-in-save_vmstate.patch [bz#1025740] +- kvm-qemu-iotests-Test-for-loading-VM-state-from-qcow2.patch [bz#1025740] +- kvm-apic-rename-apic-specific-bitopts.patch [bz#1001216] +- kvm-hw-import-bitmap-operations-in-qdev-core-header.patch [bz#1001216] +- kvm-qemu-help-Sort-devices-by-logical-functionality.patch [bz#1001216] +- kvm-devices-Associate-devices-to-their-logical-category.patch [bz#1001216] +- kvm-Mostly-revert-qemu-help-Sort-devices-by-logical-func.patch [bz#1001216] +- kvm-qdev-monitor-Group-device_add-help-and-info-qdm-by-c.patch [bz#1001216] +- kvm-qdev-Replace-no_user-by-cannot_instantiate_with_devi.patch [bz#1001216] +- kvm-sysbus-Set-cannot_instantiate_with_device_add_yet.patch [bz#1001216] +- kvm-cpu-Document-why-cannot_instantiate_with_device_add_.patch [bz#1001216] +- kvm-apic-Document-why-cannot_instantiate_with_device_add.patch [bz#1001216] +- kvm-pci-host-Consistently-set-cannot_instantiate_with_de.patch [bz#1001216] +- kvm-ich9-Document-why-cannot_instantiate_with_device_add.patch [bz#1001216] +- kvm-piix3-piix4-Clean-up-use-of-cannot_instantiate_with_.patch [bz#1001216] +- kvm-vt82c686-Clean-up-use-of-cannot_instantiate_with_dev.patch [bz#1001216] +- kvm-isa-Clean-up-use-of-cannot_instantiate_with_device_a.patch [bz#1001216] +- kvm-qdev-Do-not-let-the-user-try-to-device_add-when-it-c.patch [bz#1001216] +- kvm-rhel-Revert-unwanted-cannot_instantiate_with_device_.patch [bz#1001216] +- kvm-rhel-Revert-downstream-changes-to-unused-default-con.patch [bz#1001076] +- kvm-rhel-Drop-cfi.pflash01-and-isa-ide-device.patch [bz#1001076] +- kvm-rhel-Drop-isa-vga-device.patch [bz#1001088] +- kvm-rhel-Make-isa-cirrus-vga-device-unavailable.patch [bz#1001088] +- kvm-rhel-Make-ccid-card-emulated-device-unavailable.patch [bz#1001123] +- kvm-x86-fix-migration-from-pre-version-12.patch [bz#1005695] +- kvm-x86-cpuid-reconstruct-leaf-0Dh-data.patch [bz#1005695] +- kvm-kvmvapic-Catch-invalid-ROM-size.patch [bz#920021] +- kvm-kvmvapic-Enter-inactive-state-on-hardware-reset.patch [bz#920021] +- kvm-kvmvapic-Clear-also-physical-ROM-address-when-enteri.patch [bz#920021] +- kvm-block-optionally-disable-live-block-jobs.patch [bz#987582] +- kvm-rpm-spec-template-disable-live-block-ops-for-rhel-en.patch [bz#987582] +- kvm-migration-disable-live-block-migration-b-i-for-rhel-.patch [bz#1022392] +- kvm-Build-ceph-rbd-only-for-rhev.patch [bz#987583] +- kvm-spec-Disable-host-cdrom-RHEL-only.patch [bz#760885] +- kvm-rhel-Make-pci-serial-2x-and-pci-serial-4x-device-una.patch [bz#1001180] +- kvm-usb-host-libusb-Fix-reset-handling.patch [bz#980415] +- kvm-usb-host-libusb-Configuration-0-may-be-a-valid-confi.patch [bz#980383] +- kvm-usb-host-libusb-Detach-kernel-drivers-earlier.patch [bz#980383] +- kvm-monitor-Remove-pci_add-command-for-Red-Hat-Enterpris.patch [bz#1010858] +- kvm-monitor-Remove-pci_del-command-for-Red-Hat-Enterpris.patch [bz#1010858] +- kvm-monitor-Remove-usb_add-del-commands-for-Red-Hat-Ente.patch [bz#1010858] +- kvm-monitor-Remove-host_net_add-remove-for-Red-Hat-Enter.patch [bz#1010858] +- kvm-fw_cfg-add-API-to-find-FW-cfg-object.patch [bz#990601] +- kvm-pvpanic-use-FWCfgState-explicitly.patch [bz#990601] +- kvm-pvpanic-initialization-cleanup.patch [bz#990601] +- kvm-pvpanic-fix-fwcfg-for-big-endian-hosts.patch [bz#990601] +- kvm-hw-misc-make-pvpanic-known-to-user.patch [bz#990601] +- kvm-gdbstub-do-not-restart-crashed-guest.patch [bz#990601] +- kvm-gdbstub-fix-for-commit-87f25c12bfeaaa0c41fb857713bbc.patch [bz#990601] +- kvm-vl-allow-cont-from-panicked-state.patch [bz#990601] +- kvm-hw-misc-don-t-create-pvpanic-device-by-default.patch [bz#990601] +- kvm-block-vhdx-add-migration-blocker.patch [bz#1007176] +- kvm-qemu-kvm.spec-add-vhdx-to-the-read-only-block-driver.patch [bz#1007176] +- kvm-qemu-kvm.spec-Add-VPC-VHD-driver-to-the-block-read-o.patch [bz#1007176] +- Resolves: bz#1001076 + (Disable or remove other block devices we won't support) +- Resolves: bz#1001088 + (Disable or remove display devices we won't support) +- Resolves: bz#1001123 + (Disable or remove device ccid-card-emulated) +- Resolves: bz#1001180 + (Disable or remove devices pci-serial-2x, pci-serial-4x) +- Resolves: bz#1001216 + (Fix no_user or provide another way make devices unavailable with -device / device_add) +- Resolves: bz#1005695 + (QEMU should hide CPUID.0Dh values that it does not support) +- Resolves: bz#1007176 + (Add VPC and VHDX file formats as supported in qemu-kvm (read-only)) +- Resolves: bz#1010858 + (Disable unused human monitor commands) +- Resolves: bz#1022392 + (Disable live-storage-migration in qemu-kvm (migrate -b/-i)) +- Resolves: bz#1025740 + (Saving VM state on qcow2 images results in VM state corruption) +- Resolves: bz#760885 + (Disable host cdrom passthrough) +- Resolves: bz#920021 + (qemu-kvm segment fault when reboot guest after hot unplug device with option ROM) +- Resolves: bz#980383 + (The usb3.0 stick can't be returned back to host after shutdown guest with usb3.0 pass-through) +- Resolves: bz#980415 + (libusbx: error [_open_sysfs_attr] open /sys/bus/usb/devices/4-1/bConfigurationValue failed ret=-1 errno=2) +- Resolves: bz#987582 + (Initial Virtualization Differentiation for RHEL7 (Live snapshots)) +- Resolves: bz#987583 + (Initial Virtualization Differentiation for RHEL7 (Ceph enablement)) +- Resolves: bz#989646 + (Support backup vendors in qemu to access qcow disk readonly) +- Resolves: bz#990601 + (pvpanic device triggers guest bugs when present by default) + +* Wed Nov 06 2013 Miroslav Rezanina - 1.5.3-14.el7 +- kvm-target-i386-remove-tabs-from-target-i386-cpu.h.patch [bz#928867] +- kvm-migrate-vPMU-state.patch [bz#928867] +- kvm-blockdev-do-not-default-cache.no-flush-to-true.patch [bz#1009993] +- kvm-virtio-blk-do-not-relay-a-previous-driver-s-WCE-conf.patch [bz#1009993] +- kvm-rng-random-use-error_setg_file_open.patch [bz#907743] +- kvm-block-mirror_complete-use-error_setg_file_open.patch [bz#907743] +- kvm-blockdev-use-error_setg_file_open.patch [bz#907743] +- kvm-cpus-use-error_setg_file_open.patch [bz#907743] +- kvm-dump-qmp_dump_guest_memory-use-error_setg_file_open.patch [bz#907743] +- kvm-savevm-qmp_xen_save_devices_state-use-error_setg_fil.patch [bz#907743] +- kvm-block-bdrv_reopen_prepare-don-t-use-QERR_OPEN_FILE_F.patch [bz#907743] +- kvm-qerror-drop-QERR_OPEN_FILE_FAILED-macro.patch [bz#907743] +- kvm-rhel-Drop-ivshmem-device.patch [bz#787463] +- kvm-usb-remove-old-usb-host-code.patch [bz#1001144] +- kvm-Add-rhel6-pxe-roms-files.patch [bz#997702] +- kvm-Add-rhel6-pxe-rom-to-redhat-rpm.patch [bz#997702] +- kvm-Fix-migration-from-rhel6.5-to-rhel7-with-ipxe.patch [bz#997702] +- kvm-pc-Don-t-prematurely-explode-QEMUMachineInitArgs.patch [bz#994490] +- kvm-pc-Don-t-explode-QEMUMachineInitArgs-into-local-vari.patch [bz#994490] +- kvm-smbios-Normalize-smbios_entry_add-s-error-handling-t.patch [bz#994490] +- kvm-smbios-Convert-to-QemuOpts.patch [bz#994490] +- kvm-smbios-Improve-diagnostics-for-conflicting-entries.patch [bz#994490] +- kvm-smbios-Make-multiple-smbios-type-accumulate-sanely.patch [bz#994490] +- kvm-smbios-Factor-out-smbios_maybe_add_str.patch [bz#994490] +- kvm-hw-Pass-QEMUMachine-to-its-init-method.patch [bz#994490] +- kvm-smbios-Set-system-manufacturer-product-version-by-de.patch [bz#994490] +- kvm-smbios-Decouple-system-product-from-QEMUMachine.patch [bz#994490] +- kvm-rhel-SMBIOS-type-1-branding.patch [bz#994490] +- kvm-Add-disable-rhev-features-option-to-configure.patch [] +- Resolves: bz#1001144 + (Disable or remove device usb-host-linux) +- Resolves: bz#1009993 + (RHEL7 guests do not issue fdatasyncs on virtio-blk) +- Resolves: bz#787463 + (disable ivshmem (was: [Hitachi 7.0 FEAT] Support ivshmem (Inter-VM Shared Memory))) +- Resolves: bz#907743 + (qemu-ga: empty reason string for OpenFileFailed error) +- Resolves: bz#928867 + (Virtual PMU support during live migration - qemu-kvm) +- Resolves: bz#994490 + (Set per-machine-type SMBIOS strings) +- Resolves: bz#997702 + (Migration from RHEL6.5 host to RHEL7.0 host is failed with virtio-net device) + +* Tue Nov 05 2013 Miroslav Rezanina - 1.5.3-13.el7 +- kvm-seabios-paravirt-allow-more-than-1TB-in-x86-guest.patch [bz#989677] +- kvm-scsi-prefer-UUID-to-VM-name-for-the-initiator-name.patch [bz#1006468] +- kvm-Fix-incorrect-rhel_rhev_conflicts-macro-usage.patch [bz#1017693] +- Resolves: bz#1006468 + (libiscsi initiator name should use vm UUID) +- Resolves: bz#1017693 + (incorrect use of rhel_rhev_conflicts) +- Resolves: bz#989677 + ([HP 7.0 FEAT]: Increase KVM guest supported memory to 4TiB) + +* Mon Nov 04 2013 Michal Novotny - 1.5.3-12.el7 +- kvm-vl-Clean-up-parsing-of-boot-option-argument.patch [bz#997817] +- kvm-qemu-option-check_params-is-now-unused-drop-it.patch [bz#997817] +- kvm-vl-Fix-boot-order-and-once-regressions-and-related-b.patch [bz#997817] +- kvm-vl-Rename-boot_devices-to-boot_order-for-consistency.patch [bz#997817] +- kvm-pc-Make-no-fd-bootchk-stick-across-boot-order-change.patch [bz#997817] +- kvm-doc-Drop-ref-to-Bochs-from-no-fd-bootchk-documentati.patch [bz#997817] +- kvm-libqtest-Plug-fd-and-memory-leaks-in-qtest_quit.patch [bz#997817] +- kvm-libqtest-New-qtest_end-to-go-with-qtest_start.patch [bz#997817] +- kvm-qtest-Don-t-reset-on-qtest-chardev-connect.patch [bz#997817] +- kvm-boot-order-test-New-covering-just-PC-for-now.patch [bz#997817] +- kvm-qemu-ga-execute-fsfreeze-freeze-in-reverse-order-of-.patch [bz#1019352] +- kvm-rbd-link-and-load-librbd-dynamically.patch [bz#989608] +- kvm-rbd-Only-look-for-qemu-specific-copy-of-librbd.so.1.patch [bz#989608] +- kvm-spec-Whitelist-rbd-block-driver.patch [bz#989608] +- Resolves: bz#1019352 + (qemu-guest-agent: "guest-fsfreeze-freeze" deadlocks if the guest have mounted disk images) +- Resolves: bz#989608 + ([7.0 FEAT] qemu runtime support for librbd backend (ceph)) +- Resolves: bz#997817 + (-boot order and -boot once regressed since RHEL-6) + +* Thu Oct 31 2013 Miroslav Rezanina - 1.5.3-11.el7 +- kvm-chardev-fix-pty_chr_timer.patch [bz#994414] +- kvm-qemu-socket-zero-initialize-SocketAddress.patch [bz#922010] +- kvm-qemu-socket-drop-pointless-allocation.patch [bz#922010] +- kvm-qemu-socket-catch-monitor_get_fd-failures.patch [bz#922010] +- kvm-qemu-char-check-optional-fields-using-has_.patch [bz#922010] +- kvm-error-add-error_setg_file_open-helper.patch [bz#922010] +- kvm-qemu-char-use-more-specific-error_setg_-variants.patch [bz#922010] +- kvm-qemu-char-print-notification-to-stderr.patch [bz#922010] +- kvm-qemu-char-fix-documentation-for-telnet-wait-socket-f.patch [bz#922010] +- kvm-qemu-char-don-t-leak-opts-on-error.patch [bz#922010] +- kvm-qemu-char-use-ChardevBackendKind-in-CharDriver.patch [bz#922010] +- kvm-qemu-char-minor-mux-chardev-fixes.patch [bz#922010] +- kvm-qemu-char-add-chardev-mux-support.patch [bz#922010] +- kvm-qemu-char-report-udp-backend-errors.patch [bz#922010] +- kvm-qemu-socket-don-t-leak-opts-on-error.patch [bz#922010] +- kvm-chardev-handle-qmp_chardev_add-KIND_MUX-failure.patch [bz#922010] +- kvm-acpi-piix4-Enable-qemu-kvm-compatibility-mode.patch [bz#1019474] +- kvm-target-i386-support-loading-of-cpu-xsave-subsection.patch [bz#1004743] +- Resolves: bz#1004743 + (XSAVE migration format not compatible between RHEL6 and RHEL7) +- Resolves: bz#1019474 + (RHEL-7 can't load piix4_pm migration section from RHEL-6.5) +- Resolves: bz#922010 + (RFE: support hotplugging chardev & serial ports) +- Resolves: bz#994414 + (hot-unplug chardev with pty backend caused qemu Segmentation fault) + +* Thu Oct 17 2013 Miroslav Rezanina - 1.5.3-10.el7 +- kvm-xhci-fix-endpoint-interval-calculation.patch [bz#1001604] +- kvm-xhci-emulate-intr-endpoint-intervals-correctly.patch [bz#1001604] +- kvm-xhci-reset-port-when-disabling-slot.patch [bz#1001604] +- kvm-Revert-usb-hub-report-status-changes-only-once.patch [bz#1001604] +- kvm-target-i386-Set-model-6-on-qemu64-qemu32-CPU-models.patch [bz#1004290] +- kvm-pc-rhel6-doesn-t-have-APIC-on-pentium-CPU-models.patch [bz#918907] +- kvm-pc-RHEL-6-had-x2apic-set-on-Opteron_G-123.patch [bz#918907] +- kvm-pc-RHEL-6-don-t-have-RDTSCP.patch [bz#918907] +- kvm-scsi-Fix-scsi_bus_legacy_add_drive-scsi-generic-with.patch [bz#1009285] +- kvm-seccomp-fine-tuning-whitelist-by-adding-times.patch [bz#1004175] +- kvm-block-add-bdrv_write_zeroes.patch [bz#921465] +- kvm-block-raw-add-bdrv_co_write_zeroes.patch [bz#921465] +- kvm-rdma-export-qemu_fflush.patch [bz#921465] +- kvm-block-migration-efficiently-encode-zero-blocks.patch [bz#921465] +- kvm-Fix-real-mode-guest-migration.patch [bz#921465] +- kvm-Fix-real-mode-guest-segments-dpl-value-in-savevm.patch [bz#921465] +- kvm-migration-add-autoconvergence-documentation.patch [bz#921465] +- kvm-migration-send-total-time-in-QMP-at-completed-stage.patch [bz#921465] +- kvm-migration-don-t-use-uninitialized-variables.patch [bz#921465] +- kvm-pc-drop-external-DSDT-loading.patch [bz#921465] +- kvm-hda-codec-refactor-common-definitions-into-a-header-.patch [bz#954195] +- kvm-hda-codec-make-mixemu-selectable-at-runtime.patch [bz#954195] +- kvm-audio-remove-CONFIG_MIXEMU-configure-option.patch [bz#954195] +- kvm-pc_piix-disable-mixer-for-6.4.0-machine-types-and-be.patch [bz#954195] +- kvm-spec-mixemu-config-option-is-no-longer-supported-and.patch [bz#954195] +- Resolves: bz#1001604 + (usb hub doesn't work properly (win7 sees downstream port #1 only).) +- Resolves: bz#1004175 + ('-sandbox on' option cause qemu-kvm process hang) +- Resolves: bz#1004290 + (Use model 6 for qemu64 and intel cpus) +- Resolves: bz#1009285 + (-device usb-storage,serial=... crashes with SCSI generic drive) +- Resolves: bz#918907 + (provide backwards-compatible RHEL specific machine types in QEMU - CPU features) +- Resolves: bz#921465 + (Migration can not finished even the "remaining ram" is already 0 kb) +- Resolves: bz#954195 + (RHEL machines <=6.4 should not use mixemu) + +* Thu Oct 10 2013 Miroslav Rezanina - 1.5.3-9.el7 +- kvm-qxl-fix-local-renderer.patch [bz#1005036] +- kvm-spec-include-userspace-iSCSI-initiator-in-block-driv.patch [bz#923843] +- kvm-linux-headers-update-to-kernel-3.10.0-26.el7.patch [bz#1008987] +- kvm-target-i386-add-feature-kvm_pv_unhalt.patch [bz#1008987] +- kvm-warn-if-num-cpus-is-greater-than-num-recommended.patch [bz#1010881] +- kvm-char-move-backends-io-watch-tag-to-CharDriverState.patch [bz#1007222] +- kvm-char-use-common-function-to-disable-callbacks-on-cha.patch [bz#1007222] +- kvm-char-remove-watch-callback-on-chardev-detach-from-fr.patch [bz#1007222] +- kvm-block-don-t-lose-data-from-last-incomplete-sector.patch [bz#1017049] +- kvm-vmdk-fix-cluster-size-check-for-flat-extents.patch [bz#1017049] +- kvm-qemu-iotests-add-monolithicFlat-creation-test-to-059.patch [bz#1017049] +- Resolves: bz#1005036 + (When using “-vga qxl” together with “-display vnc=:5” or “-display sdl” qemu displays pixel garbage) +- Resolves: bz#1007222 + (QEMU core dumped when do hot-unplug virtio serial port during transfer file between host to guest with virtio serial through TCP socket) +- Resolves: bz#1008987 + (pvticketlocks: add kvm feature kvm_pv_unhalt) +- Resolves: bz#1010881 + (backport vcpu soft limit warning) +- Resolves: bz#1017049 + (qemu-img refuses to open the vmdk format image its created) +- Resolves: bz#923843 + (include userspace iSCSI initiator in block driver whitelist) + +* Wed Oct 09 2013 Miroslav Rezanina - qemu-kvm-1.5.3-8.el7 +- kvm-vmdk-Make-VMDK3Header-and-VmdkGrainMarker-QEMU_PACKE.patch [bz#995866] +- kvm-vmdk-use-unsigned-values-for-on-disk-header-fields.patch [bz#995866] +- kvm-qemu-iotests-add-poke_file-utility-function.patch [bz#995866] +- kvm-qemu-iotests-add-empty-test-case-for-vmdk.patch [bz#995866] +- kvm-vmdk-check-granularity-field-in-opening.patch [bz#995866] +- kvm-vmdk-check-l2-table-size-when-opening.patch [bz#995866] +- kvm-vmdk-check-l1-size-before-opening-image.patch [bz#995866] +- kvm-vmdk-use-heap-allocation-for-whole_grain.patch [bz#995866] +- kvm-vmdk-rename-num_gtes_per_gte-to-num_gtes_per_gt.patch [bz#995866] +- kvm-vmdk-Move-l1_size-check-into-vmdk_add_extent.patch [bz#995866] +- kvm-vmdk-fix-L1-and-L2-table-size-in-vmdk3-open.patch [bz#995866] +- kvm-vmdk-support-vmfsSparse-files.patch [bz#995866] +- kvm-vmdk-support-vmfs-files.patch [bz#995866] +- Resolves: bz#995866 + (fix vmdk support to ESX images) + +* Thu Sep 26 2013 Miroslav Rezanina - qemu-kvm-1.5.3-7.el7 +- kvm-spice-fix-display-initialization.patch [bz#974887] +- kvm-Remove-i82550-network-card-emulation.patch [bz#921983] +- kvm-Remove-usb-wacom-tablet.patch [bz#903914] +- kvm-Disable-usb-uas.patch [bz#903914] +- kvm-Disable-vhost-scsi.patch [bz#994642] +- kvm-Remove-no-hpet-option.patch [bz#947441] +- kvm-Disable-isa-parallel.patch [bz#1002286] +- kvm-xhci-implement-warm-port-reset.patch [bz#949514] +- kvm-usb-add-serial-bus-property.patch [bz#953304] +- kvm-rhel6-compat-usb-serial-numbers.patch [bz#953304] +- kvm-vmdk-fix-comment-for-vmdk_co_write_zeroes.patch [bz#995866] +- kvm-gluster-Add-image-resize-support.patch [bz#1007226] +- kvm-block-Introduce-bs-zero_beyond_eof.patch [bz#1007226] +- kvm-block-Produce-zeros-when-protocols-reading-beyond-en.patch [bz#1007226] +- kvm-gluster-Abort-on-AIO-completion-failure.patch [bz#1007226] +- kvm-Preparation-for-usb-bt-dongle-conditional-build.patch [bz#1001131] +- kvm-Remove-dev-bluetooth.c-dependency-from-vl.c.patch [bz#1001131] +- kvm-exec-Fix-Xen-RAM-allocation-with-unusual-options.patch [bz#1009328] +- kvm-exec-Clean-up-fall-back-when-mem-path-allocation-fai.patch [bz#1009328] +- kvm-exec-Reduce-ifdeffery-around-mem-path.patch [bz#1009328] +- kvm-exec-Simplify-the-guest-physical-memory-allocation-h.patch [bz#1009328] +- kvm-exec-Drop-incorrect-dead-S390-code-in-qemu_ram_remap.patch [bz#1009328] +- kvm-exec-Clean-up-unnecessary-S390-ifdeffery.patch [bz#1009328] +- kvm-exec-Don-t-abort-when-we-can-t-allocate-guest-memory.patch [bz#1009328] +- kvm-pc_sysfw-Fix-ISA-BIOS-init-for-ridiculously-big-flas.patch [bz#1009328] +- kvm-virtio-scsi-Make-type-virtio-scsi-common-abstract.patch [bz#903918] +- kvm-qga-move-logfiles-to-new-directory-for-easier-SELinu.patch [bz#1009491] +- kvm-target-i386-add-cpu64-rhel6-CPU-model.patch [bz#918907] +- kvm-fix-steal-time-MSR-vmsd-callback-to-proper-opaque-ty.patch [bz#903889] +- Resolves: bz#1001131 + (Disable or remove device usb-bt-dongle) +- Resolves: bz#1002286 + (Disable or remove device isa-parallel) +- Resolves: bz#1007226 + (Introduce bs->zero_beyond_eof) +- Resolves: bz#1009328 + ([RFE] Nicer error report when qemu-kvm can't allocate guest RAM) +- Resolves: bz#1009491 + (move qga logfiles to new /var/log/qemu-ga/ directory [RHEL-7]) +- Resolves: bz#903889 + (The value of steal time in "top" command always is "0.0% st" after guest migration) +- Resolves: bz#903914 + (Disable or remove usb related devices that we will not support) +- Resolves: bz#903918 + (Disable or remove emulated SCSI devices we will not support) +- Resolves: bz#918907 + (provide backwards-compatible RHEL specific machine types in QEMU - CPU features) +- Resolves: bz#921983 + (Disable or remove emulated network devices that we will not support) +- Resolves: bz#947441 + (HPET device must be disabled) +- Resolves: bz#949514 + (fail to passthrough the USB3.0 stick to windows guest with xHCI controller under pc-i440fx-1.4) +- Resolves: bz#953304 + (Serial number of some USB devices must be fixed for older RHEL machine types) +- Resolves: bz#974887 + (the screen of guest fail to display correctly when use spice + qxl driver) +- Resolves: bz#994642 + (should disable vhost-scsi) +- Resolves: bz#995866 + (fix vmdk support to ESX images) + +* Mon Sep 23 2013 Paolo Bonzini - qemu-kvm-1.5.3-6.el7 +- re-enable spice +- Related: #979953 + +* Mon Sep 23 2013 Paolo Bonzini - qemu-kvm-1.5.3-5.el7 +- temporarily disable spice until libiscsi rebase is complete +- Related: #979953 + +* Thu Sep 19 2013 Michal Novotny - qemu-kvm-1.5.3-4.el7 +- kvm-block-package-preparation-code-in-qmp_transaction.patch [bz#1005818] +- kvm-block-move-input-parsing-code-in-qmp_transaction.patch [bz#1005818] +- kvm-block-package-committing-code-in-qmp_transaction.patch [bz#1005818] +- kvm-block-package-rollback-code-in-qmp_transaction.patch [bz#1005818] +- kvm-block-make-all-steps-in-qmp_transaction-as-callback.patch [bz#1005818] +- kvm-blockdev-drop-redundant-proto_drv-check.patch [bz#1005818] +- kvm-block-Don-t-parse-protocol-from-file.filename.patch [bz#1005818] +- kvm-Revert-block-Disable-driver-specific-options-for-1.5.patch [bz#1005818] +- kvm-qcow2-Add-refcount-update-reason-to-all-callers.patch [bz#1005818] +- kvm-qcow2-Options-to-enable-discard-for-freed-clusters.patch [bz#1005818] +- kvm-qcow2-Batch-discards.patch [bz#1005818] +- kvm-block-Always-enable-discard-on-the-protocol-level.patch [bz#1005818] +- kvm-qapi.py-Avoid-code-duplication.patch [bz#1005818] +- kvm-qapi.py-Allow-top-level-type-reference-for-command-d.patch [bz#1005818] +- kvm-qapi-schema-Use-BlockdevSnapshot-type-for-blockdev-s.patch [bz#1005818] +- kvm-qapi-types.py-Implement-base-for-unions.patch [bz#1005818] +- kvm-qapi-visit.py-Split-off-generate_visit_struct_fields.patch [bz#1005818] +- kvm-qapi-visit.py-Implement-base-for-unions.patch [bz#1005818] +- kvm-docs-Document-QAPI-union-types.patch [bz#1005818] +- kvm-qapi-Add-visitor-for-implicit-structs.patch [bz#1005818] +- kvm-qapi-Flat-unions-with-arbitrary-discriminator.patch [bz#1005818] +- kvm-qapi-Add-consume-argument-to-qmp_input_get_object.patch [bz#1005818] +- kvm-qapi.py-Maintain-a-list-of-union-types.patch [bz#1005818] +- kvm-qapi-qapi-types.py-native-list-support.patch [bz#1005818] +- kvm-qapi-Anonymous-unions.patch [bz#1005818] +- kvm-block-Allow-driver-option-on-the-top-level.patch [bz#1005818] +- kvm-QemuOpts-Add-qemu_opt_unset.patch [bz#1005818] +- kvm-blockdev-Rename-I-O-throttling-options-for-QMP.patch [bz#1005818] +- kvm-qemu-iotests-Update-051-reference-output.patch [bz#1005818] +- kvm-blockdev-Rename-readonly-option-to-read-only.patch [bz#1005818] +- kvm-blockdev-Split-up-cache-option.patch [bz#1005818] +- kvm-qcow2-Use-dashes-instead-of-underscores-in-options.patch [bz#1005818] +- kvm-qemu-iotests-filter-QEMU-version-in-monitor-banner.patch [bz#1006959] +- kvm-tests-set-MALLOC_PERTURB_-to-expose-memory-bugs.patch [bz#1006959] +- kvm-qemu-iotests-Whitespace-cleanup.patch [bz#1006959] +- kvm-qemu-iotests-Fixed-test-case-026.patch [bz#1006959] +- kvm-qemu-iotests-Fix-test-038.patch [bz#1006959] +- kvm-qemu-iotests-Remove-lsi53c895a-tests-from-051.patch [bz#1006959] +- Resolves: bz#1005818 + (qcow2: Backport discard command line options) +- Resolves: bz#1006959 + (qemu-iotests false positives) + +* Thu Aug 29 2013 Miroslav Rezanina - qemu-kvm-1.5.3-3.el7 +- Fix rhel/rhev split + +* Thu Aug 29 2013 Miroslav Rezanina - qemu-kvm-1.5.3-2.el7 +- kvm-osdep-add-qemu_get_local_state_pathname.patch [bz#964304] +- kvm-qga-determine-default-state-dir-and-pidfile-dynamica.patch [bz#964304] +- kvm-configure-don-t-save-any-fixed-local_statedir-for-wi.patch [bz#964304] +- kvm-qga-create-state-directory-on-win32.patch [bz#964304] +- kvm-qga-save-state-directory-in-ga_install_service-RHEL-.patch [bz#964304] +- kvm-Makefile-create-.-var-run-when-installing-the-POSIX-.patch [bz#964304] +- kvm-qemu-option-Fix-qemu_opts_find-for-null-id-arguments.patch [bz#980782] +- kvm-qemu-option-Fix-qemu_opts_set_defaults-for-corner-ca.patch [bz#980782] +- kvm-vl-New-qemu_get_machine_opts.patch [bz#980782] +- kvm-Fix-machine-options-accel-kernel_irqchip-kvm_shadow_.patch [bz#980782] +- kvm-microblaze-Fix-latent-bug-with-default-DTB-lookup.patch [bz#980782] +- kvm-Simplify-machine-option-queries-with-qemu_get_machin.patch [bz#980782] +- kvm-pci-add-VMSTATE_MSIX.patch [bz#838170] +- kvm-xhci-add-XHCISlot-addressed.patch [bz#838170] +- kvm-xhci-add-xhci_alloc_epctx.patch [bz#838170] +- kvm-xhci-add-xhci_init_epctx.patch [bz#838170] +- kvm-xhci-add-live-migration-support.patch [bz#838170] +- kvm-pc-set-level-xlevel-correctly-on-486-qemu32-CPU-mode.patch [bz#918907] +- kvm-pc-Remove-incorrect-rhel6.x-compat-model-value-for-C.patch [bz#918907] +- kvm-pc-rhel6.x-has-x2apic-present-on-Conroe-Penryn-Nehal.patch [bz#918907] +- kvm-pc-set-compat-CPUID-0x80000001-.EDX-bits-on-Westmere.patch [bz#918907] +- kvm-pc-Remove-PCLMULQDQ-from-Westmere-on-rhel6.x-machine.patch [bz#918907] +- kvm-pc-SandyBridge-rhel6.x-compat-fixes.patch [bz#918907] +- kvm-pc-Haswell-doesn-t-have-rdtscp-on-rhel6.x.patch [bz#918907] +- kvm-i386-fix-LAPIC-TSC-deadline-timer-save-restore.patch [bz#972433] +- kvm-all.c-max_cpus-should-not-exceed-KVM-vcpu-limit.patch [bz#996258] +- kvm-add-timestamp-to-error_report.patch [bz#906937] +- kvm-Convert-stderr-message-calling-error_get_pretty-to-e.patch [bz#906937] +- Resolves: bz#838170 + (Add live migration support for USB [xhci, usb-uas]) +- Resolves: bz#906937 + ([Hitachi 7.0 FEAT][QEMU]Add a time stamp to error message (*)) +- Resolves: bz#918907 + (provide backwards-compatible RHEL specific machine types in QEMU - CPU features) +- Resolves: bz#964304 + (Windows guest agent service failed to be started) +- Resolves: bz#972433 + ("INFO: rcu_sched detected stalls" after RHEL7 kvm vm migrated) +- Resolves: bz#980782 + (kernel_irqchip defaults to off instead of on without -machine) +- Resolves: bz#996258 + (boot guest with maxcpu=255 successfully but actually max number of vcpu is 160) + +* Wed Aug 28 2013 Miroslav Rezanina - 10:1.5.3-1 +- Rebase to qemu 1.5.3 + +* Tue Aug 20 2013 Miroslav Rezanina - 10:1.5.2-4 +- qemu: guest agent creates files with insecure permissions in deamon mode [rhel-7.0] (rhbz 974444) +- update qemu-ga config & init script in RHEL7 wrt. fsfreeze hook (rhbz 969942) +- RHEL7 does not have equivalent functionality for __com.redhat_qxl_screendump (rhbz 903910) +- SEP flag behavior for CPU models of RHEL6 machine types should be compatible (rhbz 960216) +- crash command can not read the dump-guest-memory file when paging=false [RHEL-7] (rhbz 981582) +- RHEL 7 qemu-kvm fails to build on F19 host due to libusb deprecated API (rhbz 996469) +- Live migration support in virtio-blk-data-plane (rhbz 995030) +- qemu-img resize can execute successfully even input invalid syntax (rhbz 992935) + +* Fri Aug 09 2013 Miroslav Rezanina - 10:1.5.2-3 +- query mem info from monitor would cause qemu-kvm hang [RHEL-7] (rhbz #970047) +- Throttle-down guest to help with live migration convergence (backport to RHEL7.0) (rhbz #985958) +- disable (for now) EFI-enabled roms (rhbz #962563) +- qemu-kvm "vPMU passthrough" mode breaks migration, shouldn't be enabled by default (rhbz #853101) +- Remove pending watches after virtserialport unplug (rhbz #992900) +- Containment of error when an SR-IOV device encounters an error... (rhbz #984604) + +* Wed Jul 31 2013 Miroslav Rezanina - 10:1.5.2-2 +- SPEC file prepared for RHEL/RHEV split (rhbz #987165) +- RHEL guest( sata disk ) can not boot up (rhbz #981723) +- Kill the "use flash device for BIOS unless KVM" misfeature (rhbz #963280) +- Provide RHEL-6 machine types (rhbz #983991) +- Change s3/s4 default to "disable". (rhbz #980840) +- Support Virtual Memory Disk Format in qemu (rhbz #836675) +- Glusterfs backend for QEMU (rhbz #805139) + +* Tue Jul 02 2013 Miroslav Rezanina - 10:1.5.2-1 +- Rebase to 1.5.2 + +* Tue Jul 02 2013 Miroslav Rezanina - 10:1.5.1-2 +- Fix package package version info (bz #952996) +- pc: Replace upstream machine types by RHEL-7 types (bz #977864) +- target-i386: Update model values on Conroe/Penryn/Nehalem CPU model (bz #861210) +- target-i386: Set level=4 on Conroe/Penryn/Nehalem (bz #861210) + +* Fri Jun 28 2013 Miroslav Rezanina - 10:1.5.1-1 +- Rebase to 1.5.1 +- Change epoch to 10 to obsolete RHEL-6 qemu-kvm-rhev package (bz #818626) + +* Fri May 24 2013 Miroslav Rezanina - 3:1.5.0-2 +- Enable werror (bz #948290) +- Enable nbd driver (bz #875871) +- Fix udev rules file location (bz #958860) +- Remove +x bit from systemd unit files (bz #965000) +- Drop unneeded kvm.modules on x86 (bz #963642) +- Fix build flags +- Enable libusb + +* Thu May 23 2013 Miroslav Rezanina - 3:1.5.0-1 +- Rebase to 1.5.0 + +* Tue Apr 23 2013 Miroslav Rezanina - 3:1.4.0-4 +- Enable build of libcacard subpackage for non-x86_64 archs (bz #873174) +- Enable build of qemu-img subpackage for non-x86_64 archs (bz #873174) +- Enable build of qemu-guest-agent subpackage for non-x86_64 archs (bz #873174) + +* Tue Apr 23 2013 Miroslav Rezanina - 3:1.4.0-3 +- Enable/disable features supported by rhel7 +- Use qemu-kvm instead of qemu in filenames and pathes + +* Fri Apr 19 2013 Daniel Mach - 3:1.4.0-2.1 +- Rebuild for cyrus-sasl + +* Fri Apr 05 2013 Miroslav Rezanina - 3:1.4.0-2 +- Synchronization with Fedora 19 package version 2:1.4.0-8 + +* Wed Apr 03 2013 Daniel Mach - 3:1.4.0-1.1 +- Rebuild for libseccomp + +* Thu Mar 07 2013 Miroslav Rezanina - 3:1.4.0-1 +- Rebase to 1.4.0 + +* Mon Feb 25 2013 Michal Novotny - 3:1.3.0-8 +- Missing package qemu-system-x86 in hardware certification kvm testing (bz#912433) +- Resolves: bz#912433 + (Missing package qemu-system-x86 in hardware certification kvm testing) + +* Fri Feb 22 2013 Alon Levy - 3:1.3.0-6 +- Bump epoch back to 3 since there has already been a 3 package release: + 3:1.2.0-20.el7 https://brewweb.devel.redhat.com/buildinfo?buildID=244866 +- Mark explicit libcacard dependency on new enough qemu-img to avoid conflict + since /usr/bin/vscclient was moved from qemu-img to libcacard subpackage. + +* Wed Feb 13 2013 Michal Novotny - 2:1.3.0-5 +- Fix patch contents for usb-redir (bz#895491) +- Resolves: bz#895491 + (PATCH: 0110-usb-redir-Add-flow-control-support.patch has been mangled on rebase !!) + +* Wed Feb 06 2013 Alon Levy - 2:1.3.0-4 +- Add patch from f19 package for libcacard missing error_set symbol. +- Resolves: bz#891552 + +* Mon Jan 07 2013 Michal Novotny - 2:1.3.0-3 +- Remove dependency on bogus qemu-kvm-kvm package [bz#870343] +- Resolves: bz#870343 + (qemu-kvm-1.2.0-16.el7 cant be installed) + +* Tue Dec 18 2012 Michal Novotny - 2:1.3.0-2 +- Rename qemu to qemu-kvm +- Move qemu-kvm to libexecdir + +* Fri Dec 07 2012 Cole Robinson - 2:1.3.0-1 +- Switch base tarball from qemu-kvm to qemu +- qemu 1.3 release +- Option to use linux VFIO driver to assign PCI devices +- Many USB3 improvements +- New paravirtualized hardware random number generator device. +- Support for Glusterfs volumes with "gluster://" -drive URI +- Block job commands for live block commit and storage migration + +* Wed Nov 28 2012 Alon Levy - 2:1.2.0-25 +* Merge libcacard into qemu, since they both use the same sources now. + +* Thu Nov 22 2012 Paolo Bonzini - 2:1.2.0-24 +- Move vscclient to qemu-common, qemu-nbd to qemu-img + +* Tue Nov 20 2012 Alon Levy - 2:1.2.0-23 +- Rewrite fix for bz #725965 based on fix for bz #867366 +- Resolve bz #867366 + +* Fri Nov 16 2012 Paolo Bonzini - 2:1.2.0-23 +- Backport --with separate_kvm support from EPEL branch + +* Fri Nov 16 2012 Paolo Bonzini - 2:1.2.0-22 +- Fix previous commit + +* Fri Nov 16 2012 Paolo Bonzini - 2:1.2.0-21 +- Backport commit 38f419f (configure: Fix CONFIG_QEMU_HELPERDIR generation, + 2012-10-17) + +* Thu Nov 15 2012 Paolo Bonzini - 2:1.2.0-20 +- Install qemu-bridge-helper as suid root +- Distribute a sample /etc/qemu/bridge.conf file + +* Thu Nov 1 2012 Hans de Goede - 2:1.2.0-19 +- Sync spice patches with upstream, minor bugfixes and set the qxl pci + device revision to 4 by default, so that guests know they can use + the new features + +* Tue Oct 30 2012 Cole Robinson - 2:1.2.0-18 +- Fix loading arm initrd if kernel is very large (bz #862766) +- Don't use reserved word 'function' in systemtap files (bz #870972) +- Drop assertion that was triggering when pausing guests w/ qxl (bz + #870972) + +* Sun Oct 28 2012 Cole Robinson - 2:1.2.0-17 +- Pull patches queued for qemu 1.2.1 + +* Fri Oct 19 2012 Paolo Bonzini - 2:1.2.0-16 +- add s390x KVM support +- distribute pre-built firmware or device trees for Alpha, Microblaze, S390 +- add missing system targets +- add missing linux-user targets +- fix previous commit + +* Thu Oct 18 2012 Dan Horák - 2:1.2.0-15 +- fix build on non-kvm arches like s390(x) + +* Wed Oct 17 2012 Paolo Bonzini - 2:1.2.0-14 +- Change SLOF Requires for the new version number + +* Thu Oct 11 2012 Paolo Bonzini - 2:1.2.0-13 +- Add ppc support to kvm.modules (original patch by David Gibson) +- Replace x86only build with kvmonly build: add separate defines and + conditionals for all packages, so that they can be chosen and + renamed in kvmonly builds and so that qemu has the appropriate requires +- Automatically pick libfdt dependancy +- Add knob to disable spice+seccomp + +* Fri Sep 28 2012 Paolo Bonzini - 2:1.2.0-12 +- Call udevadm on post, fixing bug 860658 + +* Fri Sep 28 2012 Hans de Goede - 2:1.2.0-11 +- Rebuild against latest spice-server and spice-protocol +- Fix non-seamless migration failing with vms with usb-redir devices, + to allow boxes to load such vms from disk + +* Tue Sep 25 2012 Hans de Goede - 2:1.2.0-10 +- Sync Spice patchsets with upstream (rhbz#860238) +- Fix building with usbredir >= 0.5.2 + +* Thu Sep 20 2012 Hans de Goede - 2:1.2.0-9 +- Sync USB and Spice patchsets with upstream + +* Sun Sep 16 2012 Richard W.M. Jones - 2:1.2.0-8 +- Use 'global' instead of 'define', and underscore in definition name, + n-v-r, and 'dist' tag of SLOF, all to fix RHBZ#855252. + +* Fri Sep 14 2012 Paolo Bonzini - 2:1.2.0-4 +- add versioned dependency from qemu-system-ppc to SLOF (BZ#855252) + +* Wed Sep 12 2012 Richard W.M. Jones - 2:1.2.0-3 +- Fix RHBZ#853408 which causes libguestfs failure. + +* Sat Sep 8 2012 Hans de Goede - 2:1.2.0-2 +- Fix crash on (seamless) migration +- Sync usbredir live migration patches with upstream + +* Fri Sep 7 2012 Hans de Goede - 2:1.2.0-1 +- New upstream release 1.2.0 final +- Add support for Spice seamless migration +- Add support for Spice dynamic monitors +- Add support for usb-redir live migration + +* Tue Sep 04 2012 Adam Jackson 1.2.0-0.5.rc1 +- Flip Requires: ceph >= foo to Conflicts: ceph < foo, so we pull in only the + libraries which we need and not the rest of ceph which we don't. + +* Tue Aug 28 2012 Cole Robinson 1.2.0-0.4.rc1 +- Update to 1.2.0-rc1 + +* Mon Aug 20 2012 Richard W.M. Jones - 1.2-0.3.20120806git3e430569 +- Backport Bonzini's vhost-net fix (RHBZ#848400). + +* Tue Aug 14 2012 Cole Robinson - 1.2-0.2.20120806git3e430569 +- Bump release number, previous build forgot but the dist bump helped us out + +* Tue Aug 14 2012 Cole Robinson - 1.2-0.1.20120806git3e430569 +- Revive qemu-system-{ppc*, sparc*} (bz 844502) +- Enable KVM support for all targets (bz 844503) + +* Mon Aug 06 2012 Cole Robinson - 1.2-0.1.20120806git3e430569.fc18 +- Update to git snapshot + +* Sun Jul 29 2012 Cole Robinson - 1.1.1-1 +- Upstream stable release 1.1.1 +- Fix systemtap tapsets (bz 831763) +- Fix VNC audio tunnelling (bz 840653) +- Don't renable ksm on update (bz 815156) +- Bump usbredir dep (bz 812097) +- Fix RPM install error on non-virt machines (bz 660629) +- Obsolete openbios to fix upgrade dependency issues (bz 694802) + +* Sat Jul 21 2012 Fedora Release Engineering - 2:1.1.0-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 10 2012 Richard W.M. Jones - 2:1.1.0-8 +- Re-diff previous patch so that it applies and actually apply it + +* Tue Jul 10 2012 Richard W.M. Jones - 2:1.1.0-7 +- Add patch to fix default machine options. This fixes libvirt + detection of qemu. +- Back out patch 1 which conflicts. + +* Fri Jul 6 2012 Hans de Goede - 2:1.1.0-5 +- Fix qemu crashing (on an assert) whenever USB-2.0 isoc transfers are used + +* Thu Jul 5 2012 Richard W.M. Jones - 2:1.1.0-4 +- Disable tests since they hang intermittently. +- Add kvmvapic.bin (replaces vapic.bin). +- Add cpus-x86_64.conf. qemu now creates /etc/qemu/target-x86_64.conf + as an empty file. +- Add qemu-icon.bmp. +- Add qemu-bridge-helper. +- Build and include virtfs-proxy-helper + man page (thanks Hans de Goede). + +* Wed Jul 4 2012 Hans de Goede - 2:1.1.0-1 +- New upstream release 1.1.0 +- Drop about a 100 spice + USB patches, which are all upstream + +* Mon Apr 23 2012 Paolo Bonzini - 2:1.0-17 +- Fix install failure due to set -e (rhbz #815272) + +* Mon Apr 23 2012 Paolo Bonzini - 2:1.0-16 +- Fix kvm.modules to exit successfully on non-KVM capable systems (rhbz #814932) + +* Thu Apr 19 2012 Hans de Goede - 2:1.0-15 +- Add a couple of backported QXL/Spice bugfixes +- Add spice volume control patches + +* Fri Apr 6 2012 Paolo Bonzini - 2:1.0-12 +- Add back PPC and SPARC user emulators +- Update binfmt rules from upstream + +* Mon Apr 2 2012 Hans de Goede - 2:1.0-11 +- Some more USB bugfixes from upstream + +* Thu Mar 29 2012 Eduardo Habkost - 2:1.0-12 +- Fix ExclusiveArch mistake that disabled all non-x86_64 builds on Fedora + +* Wed Mar 28 2012 Eduardo Habkost - 2:1.0-11 +- Use --with variables for build-time settings + +* Wed Mar 28 2012 Daniel P. Berrange - 2:1.0-10 +- Switch to use iPXE for netboot ROMs + +* Thu Mar 22 2012 Daniel P. Berrange - 2:1.0-9 +- Remove O_NOATIME for 9p filesystems + +* Mon Mar 19 2012 Daniel P. Berrange - 2:1.0-8 +- Move udev rules to /lib/udev/rules.d (rhbz #748207) + +* Fri Mar 9 2012 Hans de Goede - 2:1.0-7 +- Add a whole bunch of USB bugfixes from upstream + +* Mon Feb 13 2012 Daniel P. Berrange - 2:1.0-6 +- Add many more missing BRs for misc QEMU features +- Enable running of test suite during build + +* Tue Feb 07 2012 Justin M. Forbes - 2:1.0-5 +- Add support for virtio-scsi + +* Sun Feb 5 2012 Richard W.M. Jones - 2:1.0-4 +- Require updated ceph for latest librbd with rbd_flush symbol. + +* Tue Jan 24 2012 Justin M. Forbes - 2:1.0-3 +- Add support for vPMU +- e1000: bounds packet size against buffer size CVE-2012-0029 + +* Fri Jan 13 2012 Justin M. Forbes - 2:1.0-2 +- Add patches for USB redirect bits +- Remove palcode-clipper, we don't build it + +* Wed Jan 11 2012 Justin M. Forbes - 2:1.0-1 +- Add patches from 1.0.1 queue + +* Fri Dec 16 2011 Justin M. Forbes - 2:1.0-1 +- Update to qemu 1.0 + +* Tue Nov 15 2011 Justin M. Forbes - 2:0.15.1-3 +- Enable spice for i686 users as well + +* Thu Nov 03 2011 Justin M. Forbes - 2:0.15.1-2 +- Fix POSTIN scriplet failure (#748281) + +* Fri Oct 21 2011 Justin M. Forbes - 2:0.15.1-1 +- Require seabios-bin >= 0.6.0-2 (#741992) +- Replace init scripts with systemd units (#741920) +- Update to 0.15.1 stable upstream + +* Fri Oct 21 2011 Paul Moore +- Enable full relro and PIE (rhbz #738812) + +* Wed Oct 12 2011 Daniel P. Berrange - 2:0.15.0-6 +- Add BR on ceph-devel to enable RBD block device + +* Wed Oct 5 2011 Daniel P. Berrange - 2:0.15.0-5 +- Create a qemu-guest-agent sub-RPM for guest installation + +* Tue Sep 13 2011 Daniel P. Berrange - 2:0.15.0-4 +- Enable DTrace tracing backend for SystemTAP (rhbz #737763) +- Enable build with curl (rhbz #737006) + +* Thu Aug 18 2011 Hans de Goede - 2:0.15.0-3 +- Add missing BuildRequires: usbredir-devel, so that the usbredir code + actually gets build + +* Thu Aug 18 2011 Richard W.M. Jones - 2:0.15.0-2 +- Add upstream qemu patch 'Allow to leave type on default in -machine' + (2645c6dcaf6ea2a51a3b6dfa407dd203004e4d11). + +* Sun Aug 14 2011 Justin M. Forbes - 2:0.15.0-1 +- Update to 0.15.0 stable release. + +* Thu Aug 04 2011 Justin M. Forbes - 2:0.15.0-0.3.201108040af4922 +- Update to 0.15.0-rc1 as we prepare for 0.15.0 release + +* Thu Aug 4 2011 Daniel P. Berrange - 2:0.15.0-0.3.2011072859fadcc +- Fix default accelerator for non-KVM builds (rhbz #724814) + +* Thu Jul 28 2011 Justin M. Forbes - 2:0.15.0-0.1.2011072859fadcc +- Update to 0.15.0-rc0 as we prepare for 0.15.0 release + +* Tue Jul 19 2011 Hans de Goede - 2:0.15.0-0.2.20110718525e3df +- Add support usb redirection over the network, see: + http://fedoraproject.org/wiki/Features/UsbNetworkRedirection +- Restore chardev flow control patches + +* Mon Jul 18 2011 Justin M. Forbes - 2:0.15.0-0.1.20110718525e3df +- Update to git snapshot as we prepare for 0.15.0 release + +* Wed Jun 22 2011 Richard W.M. Jones - 2:0.14.0-9 +- Add BR libattr-devel. This caused the -fstype option to be disabled. + https://www.redhat.com/archives/libvir-list/2011-June/thread.html#01017 + +* Mon May 2 2011 Hans de Goede - 2:0.14.0-8 +- Fix a bug in the spice flow control patches which breaks the tcp chardev + +* Tue Mar 29 2011 Justin M. Forbes - 2:0.14.0-7 +- Disable qemu-ppc and qemu-sparc packages (#679179) + +* Mon Mar 28 2011 Justin M. Forbes - 2:0.14.0-6 +- Spice fixes for flow control. + +* Tue Mar 22 2011 Dan Horák - 2:0.14.0-5 +- be more careful when removing the -g flag on s390 + +* Fri Mar 18 2011 Justin M. Forbes - 2:0.14.0-4 +- Fix thinko on adding the most recent patches. + +* Wed Mar 16 2011 Justin M. Forbes - 2:0.14.0-3 +- Fix migration issue with vhost +- Fix qxl locking issues for spice + +* Wed Mar 02 2011 Justin M. Forbes - 2:0.14.0-2 +- Re-enable sparc and cris builds + +* Thu Feb 24 2011 Justin M. Forbes - 2:0.14.0-1 +- Update to 0.14.0 release + +* Fri Feb 11 2011 Justin M. Forbes - 2:0.14.0-0.1.20110210git7aa8c46 +- Update git snapshot +- Temporarily disable qemu-cris and qemu-sparc due to build errors (to be resolved shorly) + +* Tue Feb 08 2011 Justin M. Forbes - 2:0.14.0-0.1.20110208git3593e6b +- Update to 0.14.0 rc git snapshot +- Add virtio-net to modules + +* Wed Nov 3 2010 Daniel P. Berrange - 2:0.13.0-2 +- Revert previous change +- Make qemu-common own the /etc/qemu directory +- Add /etc/qemu/target-x86_64.conf to qemu-system-x86 regardless + of host architecture. + +* Wed Nov 03 2010 Dan Horák - 2:0.13.0-2 +- Remove kvm config file on non-x86 arches (part of #639471) +- Own the /etc/qemu directory + +* Mon Oct 18 2010 Justin M. Forbes - 2:0.13.0-1 +- Update to 0.13.0 upstream release +- Fixes for vhost +- Fix mouse in certain guests (#636887) +- Fix issues with WinXP guest install (#579348) +- Resolve build issues with S390 (#639471) +- Fix Windows XP on Raw Devices (#631591) + +* Tue Oct 05 2010 jkeating - 2:0.13.0-0.7.rc1.1 +- Rebuilt for gcc bug 634757 + +* Tue Sep 21 2010 Justin M. Forbes - 2:0.13.0-0.7.rc1 +- Flip qxl pci id from unstable to stable (#634535) +- KSM Fixes from upstream (#558281) + +* Tue Sep 14 2010 Justin M. Forbes - 2:0.13.0-0.6.rc1 +- Move away from git snapshots as 0.13 is close to release +- Updates for spice 0.6 + +* Tue Aug 10 2010 Justin M. Forbes - 2:0.13.0-0.5.20100809git25fdf4a +- Fix typo in e1000 gpxe rom requires. +- Add links to newer vgabios + +* Tue Aug 10 2010 Justin M. Forbes - 2:0.13.0-0.4.20100809git25fdf4a +- Disable spice on 32bit, it is not supported and buildreqs don't exist. + +* Mon Aug 9 2010 Justin M. Forbes - 2:0.13.0-0.3.20100809git25fdf4a +- Updates from upstream towards 0.13 stable +- Fix requires on gpxe +- enable spice now that buildreqs are in the repository. +- ksmtrace has moved to a separate upstream package + +* Tue Jul 27 2010 Justin M. Forbes - 2:0.13.0-0.2.20100727gitb81fe95 +- add texinfo buildreq for manpages. + +* Tue Jul 27 2010 Justin M. Forbes - 2:0.13.0-0.1.20100727gitb81fe95 +- Update to 0.13.0 upstream snapshot +- ksm init fixes from upstream + +* Tue Jul 20 2010 Dan Horák - 2:0.12.3-8 +- Add avoid-llseek patch from upstream needed for building on s390(x) +- Don't use parallel make on s390(x) + +* Tue Jun 22 2010 Amit Shah - 2:0.12.3-7 +- Add vvfat hardening patch from upstream (#605202) + +* Fri Apr 23 2010 Justin M. Forbes - 2:0.12.3-6 +- Change requires to the noarch seabios-bin +- Add ownership of docdir to qemu-common (#572110) +- Fix "Cannot boot from non-existent NIC" error when using virt-install (#577851) + +* Thu Apr 15 2010 Justin M. Forbes - 2:0.12.3-5 +- Update virtio console patches from upstream + +* Thu Mar 11 2010 Justin M. Forbes - 2:0.12.3-4 +- Detect cdrom via ioctl (#473154) +- re add increased buffer for USB control requests (#546483) + +* Wed Mar 10 2010 Justin M. Forbes - 2:0.12.3-3 +- Migration clear the fd in error cases (#518032) + +* Tue Mar 09 2010 Justin M. Forbes - 2:0.12.3-2 +- Allow builds --with x86only +- Add libaio-devel buildreq for aio support + +* Fri Feb 26 2010 Justin M. Forbes - 2:0.12.3-1 +- Update to 0.12.3 upstream +- vhost-net migration/restart fixes +- Add F-13 machine type +- virtio-serial fixes + +* Tue Feb 09 2010 Justin M. Forbes - 2:0.12.2-6 +- Add vhost net support. + +* Thu Feb 04 2010 Justin M. Forbes - 2:0.12.2-5 +- Avoid creating too large iovecs in multiwrite merge (#559717) +- Don't try to set max_kernel_pages during ksm init on newer kernels (#558281) +- Add logfile options for ksmtuned debug. + +* Wed Jan 27 2010 Amit Shah - 2:0.12.2-4 +- Remove build dependency on iasl now that we have seabios + +* Wed Jan 27 2010 Amit Shah - 2:0.12.2-3 +- Remove source target for 0.12.1.2 + +* Wed Jan 27 2010 Amit Shah - 2:0.12.2-2 +- Add virtio-console patches from upstream for the F13 VirtioSerial feature + +* Mon Jan 25 2010 Justin M. Forbes - 2:0.12.2-1 +- Update to 0.12.2 upstream + +* Sun Jan 10 2010 Justin M. Forbes - 2:0.12.1.2-3 +- Point to seabios instead of bochs, and add a requires for seabios + +* Mon Jan 4 2010 Justin M. Forbes - 2:0.12.1.2-2 +- Remove qcow2 virtio backing file patch + +* Mon Jan 4 2010 Justin M. Forbes - 2:0.12.1.2-1 +- Update to 0.12.1.2 upstream +- Remove patches included in upstream + +* Fri Nov 20 2009 Mark McLoughlin - 2:0.11.0-12 +- Fix a use-after-free crasher in the slirp code (#539583) +- Fix overflow in the parallels image format support (#533573) + +* Wed Nov 4 2009 Mark McLoughlin - 2:0.11.0-11 +- Temporarily disable preadv/pwritev support to fix data corruption (#526549) + +* Tue Nov 3 2009 Justin M. Forbes - 2:0.11.0-10 +- Default ksm and ksmtuned services on. + +* Thu Oct 29 2009 Mark McLoughlin - 2:0.11.0-9 +- Fix dropped packets with non-virtio NICs (#531419) + +* Wed Oct 21 2009 Glauber Costa - 2:0.11.0-8 +- Properly save kvm time registers (#524229) + +* Mon Oct 19 2009 Mark McLoughlin - 2:0.11.0-7 +- Fix potential segfault from too small MSR_COUNT (#528901) + +* Fri Oct 9 2009 Mark McLoughlin - 2:0.11.0-6 +- Fix fs errors with virtio and qcow2 backing file (#524734) +- Fix ksm initscript errors on kernel missing ksm (#527653) +- Add missing Requires(post): getent, useradd, groupadd (#527087) + +* Tue Oct 6 2009 Mark McLoughlin - 2:0.11.0-5 +- Add 'retune' verb to ksmtuned init script + +* Mon Oct 5 2009 Mark McLoughlin - 2:0.11.0-4 +- Use rtl8029 PXE rom for ne2k_pci, not ne (#526777) +- Also, replace the gpxe-roms-qemu pkg requires with file-based requires + +* Thu Oct 1 2009 Justin M. Forbes - 2:0.11.0-3 +- Improve error reporting on file access (#524695) + +* Mon Sep 28 2009 Mark McLoughlin - 2:0.11.0-2 +- Fix pci hotplug to not exit if supplied an invalid NIC model (#524022) + +* Mon Sep 28 2009 Mark McLoughlin - 2:0.11.0-1 +- Update to 0.11.0 release +- Drop a couple of upstreamed patches + +* Wed Sep 23 2009 Mark McLoughlin - 2:0.10.92-5 +- Fix issue causing NIC hotplug confusion when no model is specified (#524022) + +* Wed Sep 16 2009 Mark McLoughlin - 2:0.10.92-4 +- Fix for KSM patch from Justin Forbes + +* Wed Sep 16 2009 Mark McLoughlin - 2:0.10.92-3 +- Add ksmtuned, also from Dan Kenigsberg +- Use %%_initddir macro + +* Wed Sep 16 2009 Mark McLoughlin - 2:0.10.92-2 +- Add ksm control script from Dan Kenigsberg + +* Mon Sep 7 2009 Mark McLoughlin - 2:0.10.92-1 +- Update to qemu-kvm-0.11.0-rc2 +- Drop upstreamed patches +- extboot install now fixed upstream +- Re-place TCG init fix (#516543) with the one gone upstream + +* Mon Sep 7 2009 Mark McLoughlin - 2:0.10.91-0.10.rc1 +- Fix MSI-X error handling on older kernels (#519787) + +* Fri Sep 4 2009 Mark McLoughlin - 2:0.10.91-0.9.rc1 +- Make pulseaudio the default audio backend (#519540, #495964, #496627) + +* Thu Aug 20 2009 Richard W.M. Jones - 2:0.10.91-0.8.rc1 +- Fix segfault when qemu-kvm is invoked inside a VM (#516543) + +* Tue Aug 18 2009 Mark McLoughlin - 2:0.10.91-0.7.rc1 +- Fix permissions on udev rules (#517571) + +* Mon Aug 17 2009 Lubomir Rintel - 2:0.10.91-0.6.rc1 +- Allow blacklisting of kvm modules (#517866) + +* Fri Aug 7 2009 Mark McLoughlin - 2:0.10.91-0.5.rc1 +- Fix virtio_net with -net user (#516022) + +* Tue Aug 4 2009 Mark McLoughlin - 2:0.10.91-0.4.rc1 +- Update to qemu-kvm-0.11-rc1; no changes from rc1-rc0 + +* Tue Aug 4 2009 Mark McLoughlin - 2:0.10.91-0.3.rc1.rc0 +- Fix extboot checksum (bug #514899) + +* Fri Jul 31 2009 Mark McLoughlin - 2:0.10.91-0.2.rc1.rc0 +- Add KSM support +- Require bochs-bios >= 2.3.8-0.8 for latest kvm bios updates + +* Thu Jul 30 2009 Mark McLoughlin - 2:0.10.91-0.1.rc1.rc0 +- Update to qemu-kvm-0.11.0-rc1-rc0 +- This is a pre-release of the official -rc1 +- A vista installer regression is blocking the official -rc1 release +- Drop qemu-prefer-sysfs-for-usb-host-devices.patch +- Drop qemu-fix-build-for-esd-audio.patch +- Drop qemu-slirp-Fix-guestfwd-for-incoming-data.patch +- Add patch to ensure extboot.bin is installed + +* Sun Jul 26 2009 Fedora Release Engineering - 2:0.10.50-14.kvm88 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Jul 23 2009 Glauber Costa - 2:0.10.50-13.kvm88 +- Fix bug 513249, -net channel option is broken + +* Thu Jul 16 2009 Daniel P. Berrange - 2:0.10.50-12.kvm88 +- Add 'qemu' user and group accounts +- Force disable xen until it can be made to build + +* Thu Jul 16 2009 Mark McLoughlin - 2:0.10.50-11.kvm88 +- Update to kvm-88, see http://www.linux-kvm.org/page/ChangeLog +- Package mutiboot.bin +- Update for how extboot is built +- Fix sf.net source URL +- Drop qemu-fix-ppc-softmmu-kvm-disabled-build.patch +- Drop qemu-fix-pcspk-build-with-kvm-disabled.patch +- Cherry-pick fix for esound support build failure + +* Wed Jul 15 2009 Daniel Berrange - 2:0.10.50-10.kvm87 +- Add udev rules to make /dev/kvm world accessible & group=kvm (rhbz #497341) +- Create a kvm group if it doesn't exist (rhbz #346151) + +* Tue Jul 07 2009 Glauber Costa - 2:0.10.50-9.kvm87 +- use pxe roms from gpxe, instead of etherboot package. + +* Fri Jul 3 2009 Mark McLoughlin - 2:0.10.50-8.kvm87 +- Prefer sysfs over usbfs for usb passthrough (#508326) + +* Sat Jun 27 2009 Mark McLoughlin - 2:0.10.50-7.kvm87 +- Update to kvm-87 +- Drop upstreamed patches +- Cherry-pick new ppc build fix from upstream +- Work around broken linux-user build on ppc +- Fix hw/pcspk.c build with --disable-kvm +- Re-enable preadv()/pwritev() since #497429 is long since fixed +- Kill petalogix-s3adsp1800.dtb, since we don't ship the microblaze target + +* Fri Jun 5 2009 Mark McLoughlin - 2:0.10.50-6.kvm86 +- Fix 'kernel requires an x86-64 CPU' error +- BuildRequires ncurses-devel to enable '-curses' option (#504226) + +* Wed Jun 3 2009 Mark McLoughlin - 2:0.10.50-5.kvm86 +- Prevent locked cdrom eject - fixes hang at end of anaconda installs (#501412) +- Avoid harmless 'unhandled wrmsr' warnings (#499712) + +* Thu May 21 2009 Mark McLoughlin - 2:0.10.50-4.kvm86 +- Update to kvm-86 release +- ChangeLog here: http://marc.info/?l=kvm&m=124282885729710 + +* Fri May 1 2009 Mark McLoughlin - 2:0.10.50-3.kvm85 +- Really provide qemu-kvm as a metapackage for comps + +* Tue Apr 28 2009 Mark McLoughlin - 2:0.10.50-2.kvm85 +- Provide qemu-kvm as a metapackage for comps + +* Mon Apr 27 2009 Mark McLoughlin - 2:0.10.50-1.kvm85 +- Update to qemu-kvm-devel-85 +- kvm-85 is based on qemu development branch, currently version 0.10.50 +- Include new qemu-io utility in qemu-img package +- Re-instate -help string for boot=on to fix virtio booting with libvirt +- Drop upstreamed patches +- Fix missing kernel/include/asm symlink in upstream tarball +- Fix target-arm build +- Fix build on ppc +- Disable preadv()/pwritev() until bug #497429 is fixed +- Kill more .kernelrelease uselessness +- Make non-kvm qemu build verbose + +* Fri Apr 24 2009 Mark McLoughlin - 2:0.10-15 +- Fix source numbering typos caused by make-release addition + +* Thu Apr 23 2009 Mark McLoughlin - 2:0.10-14 +- Improve instructions for generating the tarball + +* Tue Apr 21 2009 Mark McLoughlin - 2:0.10-13 +- Enable pulseaudio driver to fix qemu lockup at shutdown (#495964) + +* Tue Apr 21 2009 Mark McLoughlin - 2:0.10-12 +- Another qcow2 image corruption fix (#496642) + +* Mon Apr 20 2009 Mark McLoughlin - 2:0.10-11 +- Fix qcow2 image corruption (#496642) + +* Sun Apr 19 2009 Mark McLoughlin - 2:0.10-10 +- Run sysconfig.modules from %%post on x86_64 too (#494739) + +* Sun Apr 19 2009 Mark McLoughlin - 2:0.10-9 +- Align VGA ROM to 4k boundary - fixes 'qemu-kvm -std vga' (#494376) + +* Tue Apr 14 2009 Glauber Costa - 2:0.10-8 +- Provide qemu-kvm conditional on the architecture. + +* Thu Apr 9 2009 Mark McLoughlin - 2:0.10-7 +- Add a much cleaner fix for vga segfault (#494002) + +* Sun Apr 5 2009 Glauber Costa - 2:0.10-6 +- Fixed qcow2 segfault creating disks over 2TB. #491943 + +* Fri Apr 3 2009 Mark McLoughlin - 2:0.10-5 +- Fix vga segfault under kvm-autotest (#494002) +- Kill kernelrelease hack; it's not needed +- Build with "make V=1" for more verbose logs + +* Thu Apr 02 2009 Glauber Costa - 2:0.10-4 +- Support botting gpxe roms. + +* Wed Apr 01 2009 Glauber Costa - 2:0.10-2 +- added missing patch. love for CVS. + +* Wed Apr 01 2009 Glauber Costa - 2:0.10-1 +- Include debuginfo for qemu-img +- Do not require qemu-common for qemu-img +- Explicitly own each of the firmware files +- remove firmwares for ppc and sparc. They should be provided by an external package. + Not that the packages exists for sparc in the secondary arch repo as noarch, but they + don't automatically get into main repos. Unfortunately it's the best we can do right + now. +- rollback a bit in time. Snapshot from avi's maint/2.6.30 + - this requires the sasl patches to come back. + - with-patched-kernel comes back. + +* Wed Mar 25 2009 Mark McLoughlin - 2:0.10-0.12.kvm20090323git +- BuildRequires pciutils-devel for device assignment (#492076) + +* Mon Mar 23 2009 Glauber Costa - 2:0.10-0.11.kvm20090323git +- Update to snapshot kvm20090323. +- Removed patch2 (upstream). +- use upstream's new split package. +- --with-patched-kernel flag not needed anymore +- Tell how to get the sources. + +* Wed Mar 18 2009 Glauber Costa - 2:0.10-0.10.kvm20090310git +- Added extboot to files list. + +* Wed Mar 11 2009 Glauber Costa - 2:0.10-0.9.kvm20090310git +- Fix wrong reference to bochs bios. + +* Wed Mar 11 2009 Glauber Costa - 2:0.10-0.8.kvm20090310git +- fix Obsolete/Provides pair +- Use kvm bios from bochs-bios package. +- Using RPM_OPT_FLAGS in configure +- Picked back audio-drv-list from kvm package + +* Tue Mar 10 2009 Glauber Costa - 2:0.10-0.7.kvm20090310git +- modify ppc patch + +* Tue Mar 10 2009 Glauber Costa - 2:0.10-0.6.kvm20090310git +- updated to kvm20090310git +- removed sasl patches (already in this release) + +* Tue Mar 10 2009 Glauber Costa - 2:0.10-0.5.kvm20090303git +- kvm.modules were being wrongly mentioned at %%install. +- update description for the x86 system package to include kvm support +- build kvm's own bios. It is still necessary while kvm uses a slightly different + irq routing mechanism + +* Thu Mar 05 2009 Glauber Costa - 2:0.10-0.4.kvm20090303git +- seems Epoch does not go into the tags. So start back here. + +* Thu Mar 05 2009 Glauber Costa - 2:0.10-0.1.kvm20090303git +- Use bochs-bios instead of bochs-bios-data +- It's official: upstream set on 0.10 + +* Thu Mar 5 2009 Daniel P. Berrange - 2:0.9.2-0.2.kvm20090303git +- Added BSD to license list, since many files are covered by BSD + +* Wed Mar 04 2009 Glauber Costa - 0.9.2-0.1.kvm20090303git +- missing a dot. shame on me + +* Wed Mar 04 2009 Glauber Costa - 0.92-0.1.kvm20090303git +- Set Epoch to 2 +- Set version to 0.92. It seems upstream keep changing minds here, so pick the lowest +- Provides KVM, Obsoletes KVM +- Only install qemu-kvm in ix86 and x86_64 +- Remove pkgdesc macros, as they were generating bogus output for rpm -qi. +- fix ppc and ppc64 builds + +* Tue Mar 03 2009 Glauber Costa - 0.10-0.3.kvm20090303git +- only execute post scripts for user package. +- added kvm tools. + +* Tue Mar 03 2009 Glauber Costa - 0.10-0.2.kvm20090303git +- put kvm.modules into cvs + +* Tue Mar 03 2009 Glauber Costa - 0.10-0.1.kvm20090303git +- Set Epoch to 1 +- Build KVM (basic build, no tools yet) +- Set ppc in ExcludeArch. This is temporary, just to fix one issue at a time. + ppc users (IBM ? ;-)) please wait a little bit. + +* Tue Mar 3 2009 Daniel P. Berrange - 1.0-0.5.svn6666 +- Support VNC SASL authentication protocol +- Fix dep on bochs-bios-data + +* Tue Mar 03 2009 Glauber Costa - 1.0-0.4.svn6666 +- use bios from bochs-bios package. + +* Tue Mar 03 2009 Glauber Costa - 1.0-0.3.svn6666 +- use vgabios from vgabios package. + +* Mon Mar 02 2009 Glauber Costa - 1.0-0.2.svn6666 +- use pxe roms from etherboot package. + +* Mon Mar 02 2009 Glauber Costa - 1.0-0.1.svn6666 +- Updated to tip svn (release 6666). Featuring split packages for qemu. + Unfortunately, still using binary blobs for the bioses. + +* Wed Feb 25 2009 Fedora Release Engineering - 0.9.1-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sun Jan 11 2009 Debarshi Ray - 0.9.1-12 +- Updated build patch. Closes Red Hat Bugzilla bug #465041. + +* Wed Dec 31 2008 Dennis Gilmore - 0.9.1-11 +- add sparcv9 and sparc64 support + +* Fri Jul 25 2008 Bill Nottingham +- Fix qemu-img summary (#456344) + +* Wed Jun 25 2008 Daniel P. Berrange - 0.9.1-10.fc10 +- Rebuild for GNU TLS ABI change + +* Wed Jun 11 2008 Daniel P. Berrange - 0.9.1-9.fc10 +- Remove bogus wildcard from files list (rhbz #450701) + +* Sat May 17 2008 Lubomir Rintel - 0.9.1-8 +- Register binary handlers also for shared libraries + +* Mon May 5 2008 Daniel P. Berrange - 0.9.1-7.fc10 +- Fix text console PTYs to be in rawmode + +* Sun Apr 27 2008 Lubomir Kundrak - 0.9.1-6 +- Register binary handler for SuperH-4 CPU + +* Wed Mar 19 2008 Daniel P. Berrange - 0.9.1-5.fc9 +- Split qemu-img tool into sub-package for smaller footprint installs + +* Wed Feb 27 2008 Daniel P. Berrange - 0.9.1-4.fc9 +- Fix block device checks for extendable disk formats (rhbz #435139) + +* Sat Feb 23 2008 Daniel P. Berrange - 0.9.1-3.fc9 +- Fix block device extents check (rhbz #433560) + +* Mon Feb 18 2008 Fedora Release Engineering - 0.9.1-2 +- Autorebuild for GCC 4.3 + +* Tue Jan 8 2008 Daniel P. Berrange - 0.9.1-1.fc9 +- Updated to 0.9.1 release +- Fix license tag syntax +- Don't mark init script as a config file + +* Wed Sep 26 2007 Daniel P. Berrange - 0.9.0-5.fc8 +- Fix rtl8139 checksum calculation for Vista (rhbz #308201) + +* Tue Aug 28 2007 Daniel P. Berrange - 0.9.0-4.fc8 +- Fix debuginfo by passing -Wl,--build-id to linker + +* Tue Aug 28 2007 David Woodhouse 0.9.0-4 +- Update licence +- Fix CDROM emulation (#253542) + +* Tue Aug 28 2007 Daniel P. Berrange - 0.9.0-3.fc8 +- Added backport of VNC password auth, and TLS+x509 cert auth +- Switch to rtl8139 NIC by default for linkstate reporting +- Fix rtl8139 mmio region mappings with multiple NICs + +* Sun Apr 1 2007 Hans de Goede 0.9.0-2 +- Fix direct loading of a linux kernel with -kernel & -initrd (bz 234681) +- Remove spurious execute bits from manpages (bz 222573) + +* Tue Feb 6 2007 David Woodhouse 0.9.0-1 +- Update to 0.9.0 + +* Wed Jan 31 2007 David Woodhouse 0.8.2-5 +- Include licences + +* Mon Nov 13 2006 Hans de Goede 0.8.2-4 +- Backport patch to make FC6 guests work by Kevin Kofler + (bz 207843). + +* Mon Sep 11 2006 David Woodhouse 0.8.2-3 +- Rebuild + +* Thu Aug 24 2006 Matthias Saou 0.8.2-2 +- Remove the target-list iteration for x86_64 since they all build again. +- Make gcc32 vs. gcc34 conditional on %%{fedora} to share the same spec for + FC5 and FC6. + +* Wed Aug 23 2006 Matthias Saou 0.8.2-1 +- Update to 0.8.2 (#200065). +- Drop upstreamed syscall-macros patch2. +- Put correct scriplet dependencies. +- Force install mode for the init script to avoid umask problems. +- Add %%postun condrestart for changes to the init script to be applied if any. +- Update description with the latest "about" from the web page (more current). +- Update URL to qemu.org one like the Source. +- Add which build requirement. +- Don't include texi files in %%doc since we ship them in html. +- Switch to using gcc34 on devel, FC5 still has gcc32. +- Add kernheaders patch to fix linux/compiler.h inclusion. +- Add target-sparc patch to fix compiling on ppc (some int32 to float). + +* Thu Jun 8 2006 David Woodhouse 0.8.1-3 +- More header abuse in modify_ldt(), change BuildRoot: + +* Wed Jun 7 2006 David Woodhouse 0.8.1-2 +- Fix up kernel header abuse + +* Tue May 30 2006 David Woodhouse 0.8.1-1 +- Update to 0.8.1 + +* Sat Mar 18 2006 David Woodhouse 0.8.0-6 +- Update linker script for PPC + +* Sat Mar 18 2006 David Woodhouse 0.8.0-5 +- Just drop $RPM_OPT_FLAGS. They're too much of a PITA + +* Sat Mar 18 2006 David Woodhouse 0.8.0-4 +- Disable stack-protector options which gcc 3.2 doesn't like + +* Fri Mar 17 2006 David Woodhouse 0.8.0-3 +- Use -mcpu= instead of -mtune= on x86_64 too +- Disable SPARC targets on x86_64, because dyngen doesn't like fnegs + +* Fri Mar 17 2006 David Woodhouse 0.8.0-2 +- Don't use -mtune=pentium4 on i386. GCC 3.2 doesn't like it + +* Fri Mar 17 2006 David Woodhouse 0.8.0-1 +- Update to 0.8.0 +- Resort to using compat-gcc-32 +- Enable ALSA + +* Mon May 16 2005 David Woodhouse 0.7.0-2 +- Proper fix for GCC 4 putting 'blr' or 'ret' in the middle of the function, + for i386, x86_64 and PPC. + +* Sat Apr 30 2005 David Woodhouse 0.7.0-1 +- Update to 0.7.0 +- Fix dyngen for PPC functions which end in unconditional branch + +* Thu Apr 7 2005 Michael Schwendt +- rebuilt + +* Sun Feb 13 2005 David Woodhouse 0.6.1-2 +- Package cleanup + +* Sun Nov 21 2004 David Woodhouse 0.6.1-1 +- Update to 0.6.1 + +* Tue Jul 20 2004 David Woodhouse 0.6.0-2 +- Compile fix from qemu CVS, add x86_64 host support + +* Wed May 12 2004 David Woodhouse 0.6.0-1 +- Update to 0.6.0. + +* Sat May 8 2004 David Woodhouse 0.5.5-1 +- Update to 0.5.5. + +* Sun May 2 2004 David Woodhouse 0.5.4-1 +- Update to 0.5.4. + +* Thu Apr 22 2004 David Woodhouse 0.5.3-1 +- Update to 0.5.3. Add init script. + +* Thu Jul 17 2003 Jeff Johnson 0.4.3-1 +- Create.