diff --git a/a30078cb-qemu-create-mp-target.patch b/a30078cb-qemu-create-mp-target.patch new file mode 100644 index 0000000..64d8354 --- /dev/null +++ b/a30078cb-qemu-create-mp-target.patch @@ -0,0 +1,336 @@ +commit a30078cb832646177defd256e77c632905f1e6d0 +Author: Michal Prívozník +Date: Wed Nov 13 15:34:50 2019 +0100 + + qemu: Create multipath targets for PRs + + If a disk has persistent reservations enabled, qemu-pr-helper + might open not only /dev/mapper/control but also individual + targets of the multipath device. We are already querying for them + in CGroups, but now we have to create them in the namespace too. + This was brought up in [1]. + + 1: https://bugzilla.redhat.com/show_bug.cgi?id=1711045#c61 + + Signed-off-by: Michal Privoznik + Tested-by: Lin Ma + Reviewed-by: Jim Fehlig + +Index: libvirt-6.1.0/src/qemu/qemu_domain.c +=================================================================== +--- libvirt-6.1.0.orig/src/qemu/qemu_domain.c ++++ libvirt-6.1.0/src/qemu/qemu_domain.c +@@ -62,6 +62,7 @@ + #include "virdomaincheckpointobjlist.h" + #include "backup_conf.h" + #include "virutil.h" ++#include "virdevmapper.h" + + #ifdef __linux__ + # include +@@ -14495,6 +14496,9 @@ qemuDomainSetupDisk(virQEMUDriverConfigP + bool hasNVMe = false; + + for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) { ++ VIR_AUTOSTRINGLIST targetPaths = NULL; ++ size_t i; ++ + if (next->type == VIR_STORAGE_TYPE_NVME) { + g_autofree char *nvmePath = NULL; + +@@ -14513,6 +14517,19 @@ qemuDomainSetupDisk(virQEMUDriverConfigP + + if (qemuDomainCreateDevice(next->path, data, false) < 0) + return -1; ++ ++ if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && ++ errno != ENOSYS && errno != EBADF) { ++ virReportSystemError(errno, ++ _("Unable to get devmapper targets for %s"), ++ next->path); ++ return -1; ++ } ++ ++ for (i = 0; targetPaths && targetPaths[i]; i++) { ++ if (qemuDomainCreateDevice(targetPaths[i], data, false) < 0) ++ return -1; ++ } + } + } + +@@ -15528,21 +15545,19 @@ qemuDomainNamespaceSetupDisk(virDomainOb + virStorageSourcePtr src) + { + virStorageSourcePtr next; +- char **paths = NULL; ++ VIR_AUTOSTRINGLIST paths = NULL; + size_t npaths = 0; + bool hasNVMe = false; +- g_autofree char *dmPath = NULL; +- g_autofree char *vfioPath = NULL; +- int ret = -1; + + for (next = src; virStorageSourceIsBacking(next); next = next->backingStore) { ++ VIR_AUTOSTRINGLIST targetPaths = NULL; + g_autofree char *tmpPath = NULL; + + if (next->type == VIR_STORAGE_TYPE_NVME) { + hasNVMe = true; + + if (!(tmpPath = virPCIDeviceAddressGetIOMMUGroupDev(&next->nvme->pciAddr))) +- goto cleanup; ++ return -1; + } else { + if (virStorageSourceIsEmpty(next) || + !virStorageSourceIsLocalStorage(next)) { +@@ -15553,30 +15568,35 @@ qemuDomainNamespaceSetupDisk(virDomainOb + tmpPath = g_strdup(next->path); + } + +- if (VIR_APPEND_ELEMENT(paths, npaths, tmpPath) < 0) +- goto cleanup; ++ if (virStringListAdd(&paths, tmpPath) < 0) ++ return -1; ++ ++ if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && ++ errno != ENOSYS && errno != EBADF) { ++ virReportSystemError(errno, ++ _("Unable to get devmapper targets for %s"), ++ next->path); ++ return -1; ++ } ++ ++ if (virStringListMerge(&paths, &targetPaths) < 0) ++ return -1; + } + + /* qemu-pr-helper might require access to /dev/mapper/control. */ +- if (src->pr) { +- dmPath = g_strdup(QEMU_DEVICE_MAPPER_CONTROL_PATH); +- if (VIR_APPEND_ELEMENT_COPY(paths, npaths, dmPath) < 0) +- goto cleanup; +- } ++ if (src->pr && ++ virStringListAdd(&paths, QEMU_DEVICE_MAPPER_CONTROL_PATH) < 0) ++ return -1; + +- if (hasNVMe) { +- vfioPath = g_strdup(QEMU_DEV_VFIO); +- if (VIR_APPEND_ELEMENT(paths, npaths, vfioPath) < 0) +- goto cleanup; +- } ++ if (hasNVMe && ++ virStringListAdd(&paths, QEMU_DEV_VFIO) < 0) ++ return -1; + ++ npaths = virStringListLength((const char **) paths); + if (qemuDomainNamespaceMknodPaths(vm, (const char **) paths, npaths) < 0) +- goto cleanup; ++ return -1; + +- ret = 0; +- cleanup: +- virStringListFreeCount(paths, npaths); +- return ret; ++ return 0; + } + + +Index: libvirt-6.1.0/src/util/virdevmapper.h +=================================================================== +--- libvirt-6.1.0.orig/src/util/virdevmapper.h ++++ libvirt-6.1.0/src/util/virdevmapper.h +@@ -20,6 +20,8 @@ + + #pragma once + ++#include "internal.h" ++ + int + virDevMapperGetTargets(const char *path, +- char ***devPaths); ++ char ***devPaths) G_GNUC_NO_INLINE; +Index: libvirt-6.1.0/src/util/virutil.h +=================================================================== +--- libvirt-6.1.0.orig/src/util/virutil.h ++++ libvirt-6.1.0/src/util/virutil.h +@@ -120,7 +120,7 @@ bool virValidateWWN(const char *wwn); + + int virGetDeviceID(const char *path, + int *maj, +- int *min); ++ int *min) G_GNUC_NO_INLINE; + int virSetDeviceUnprivSGIO(const char *path, + const char *sysfs_dir, + int unpriv_sgio); +Index: libvirt-6.1.0/tests/qemuhotplugmock.c +=================================================================== +--- libvirt-6.1.0.orig/tests/qemuhotplugmock.c ++++ libvirt-6.1.0/tests/qemuhotplugmock.c +@@ -19,7 +19,24 @@ + #include + + #include "qemu/qemu_hotplug.h" ++#include "qemu/qemu_process.h" + #include "conf/domain_conf.h" ++#include "virdevmapper.h" ++#include "virutil.h" ++#include "virmock.h" ++ ++static int (*real_virGetDeviceID)(const char *path, int *maj, int *min); ++static bool (*real_virFileExists)(const char *path); ++ ++static void ++init_syms(void) ++{ ++ if (real_virFileExists) ++ return; ++ ++ VIR_MOCK_REAL_INIT(virGetDeviceID); ++ VIR_MOCK_REAL_INIT(virFileExists); ++} + + unsigned long long + qemuDomainGetUnplugTimeout(virDomainObjPtr vm G_GNUC_UNUSED) +@@ -31,3 +48,61 @@ qemuDomainGetUnplugTimeout(virDomainObjP + return 200; + return 100; + } ++ ++ ++int ++virDevMapperGetTargets(const char *path, ++ char ***devPaths) ++{ ++ *devPaths = NULL; ++ ++ if (STREQ(path, "/dev/mapper/virt")) { ++ *devPaths = g_new(char *, 4); ++ (*devPaths)[0] = g_strdup("/dev/block/8:0"); /* /dev/sda */ ++ (*devPaths)[1] = g_strdup("/dev/block/8:16"); /* /dev/sdb */ ++ (*devPaths)[2] = g_strdup("/dev/block/8:32"); /* /dev/sdc */ ++ (*devPaths)[3] = NULL; ++ } ++ ++ return 0; ++} ++ ++ ++int ++virGetDeviceID(const char *path, int *maj, int *min) ++{ ++ init_syms(); ++ ++ if (STREQ(path, "/dev/mapper/virt")) { ++ *maj = 254; ++ *min = 0; ++ return 0; ++ } ++ ++ return real_virGetDeviceID(path, maj, min); ++} ++ ++ ++bool ++virFileExists(const char *path) ++{ ++ init_syms(); ++ ++ if (STREQ(path, "/dev/mapper/virt")) ++ return true; ++ ++ return real_virFileExists(path); ++} ++ ++ ++int ++qemuProcessStartManagedPRDaemon(virDomainObjPtr vm G_GNUC_UNUSED) ++{ ++ return 0; ++} ++ ++ ++void ++qemuProcessKillManagedPRDaemon(virDomainObjPtr vm G_GNUC_UNUSED) ++{ ++} +Index: libvirt-6.1.0/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-multipath.xml +=================================================================== +--- /dev/null ++++ libvirt-6.1.0/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-multipath.xml +@@ -0,0 +1,8 @@ ++ ++ ++ ++ ++ ++ ++
++ +Index: libvirt-6.1.0/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-scsi-multipath.xml +=================================================================== +--- /dev/null ++++ libvirt-6.1.0/tests/qemuhotplugtestdomains/qemuhotplug-base-live+disk-scsi-multipath.xml +@@ -0,0 +1,62 @@ ++ ++ hotplug ++ d091ea82-29e6-2e34-3005-f02617b36e87 ++ 4194304 ++ 4194304 ++ 4 ++ ++ hvm ++ ++ ++ ++ ++ ++ ++ ++ ++ destroy ++ restart ++ restart ++ ++ /usr/bin/qemu-system-x86_64 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
++ ++ ++ ++
++ ++ ++ ++
++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ diff --git a/aeb909bf-qemu-multipath-fix.patch b/aeb909bf-qemu-multipath-fix.patch new file mode 100644 index 0000000..6c504bd --- /dev/null +++ b/aeb909bf-qemu-multipath-fix.patch @@ -0,0 +1,71 @@ +commit aeb909bf9b4c3fa48d017475545df94f7c5d3b3a +Author: Michal Prívozník +Date: Thu Mar 19 12:51:55 2020 +0100 + + qemu: Don't crash when getting targets for a multipath + + In one of my previous commits I've introduced code that creates + all devices for given (possible) multipath target. But I've made + a mistake there - the code accesses 'next->path' without checking + if the disk source is local. Note that the 'next->path' is + NULL/doesn't make sense for VIR_STORAGE_TYPE_NVME. + + Fixes: a30078cb832646177defd256e77c632905f1e6d0 + Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1814947 + + Signed-off-by: Michal Privoznik + Reviewed-by: Peter Krempa + Reviewed-by: Ján Tomko + +Index: libvirt-6.1.0/src/qemu/qemu_domain.c +=================================================================== +--- libvirt-6.1.0.orig/src/qemu/qemu_domain.c ++++ libvirt-6.1.0/src/qemu/qemu_domain.c +@@ -15550,7 +15550,6 @@ qemuDomainNamespaceSetupDisk(virDomainOb + bool hasNVMe = false; + + for (next = src; virStorageSourceIsBacking(next); next = next->backingStore) { +- VIR_AUTOSTRINGLIST targetPaths = NULL; + g_autofree char *tmpPath = NULL; + + if (next->type == VIR_STORAGE_TYPE_NVME) { +@@ -15559,6 +15558,8 @@ qemuDomainNamespaceSetupDisk(virDomainOb + if (!(tmpPath = virPCIDeviceAddressGetIOMMUGroupDev(&next->nvme->pciAddr))) + return -1; + } else { ++ VIR_AUTOSTRINGLIST targetPaths = NULL; ++ + if (virStorageSourceIsEmpty(next) || + !virStorageSourceIsLocalStorage(next)) { + /* Not creating device. Just continue. */ +@@ -15566,20 +15567,20 @@ qemuDomainNamespaceSetupDisk(virDomainOb + } + + tmpPath = g_strdup(next->path); +- } + +- if (virStringListAdd(&paths, tmpPath) < 0) +- return -1; ++ if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && ++ errno != ENOSYS && errno != EBADF) { ++ virReportSystemError(errno, ++ _("Unable to get devmapper targets for %s"), ++ next->path); ++ return -1; ++ } + +- if (virDevMapperGetTargets(next->path, &targetPaths) < 0 && +- errno != ENOSYS && errno != EBADF) { +- virReportSystemError(errno, +- _("Unable to get devmapper targets for %s"), +- next->path); +- return -1; ++ if (virStringListMerge(&paths, &targetPaths) < 0) ++ return -1; + } + +- if (virStringListMerge(&paths, &targetPaths) < 0) ++ if (virStringListAdd(&paths, tmpPath) < 0) + return -1; + } + diff --git a/libvirt.changes b/libvirt.changes index c4ee630..64f6301 100644 --- a/libvirt.changes +++ b/libvirt.changes @@ -1,3 +1,24 @@ +------------------------------------------------------------------- +Thu Mar 19 22:59:45 UTC 2020 - James Fehlig + +- libxl: Bump minimum supported Xen version to 4.9, allowing use + of newer libxl APIs for retrieving memory statistics + suse-bump-xen-version.patch + bsc#1157490, bsc#1167007 + +------------------------------------------------------------------- +Tue Mar 17 19:50:01 UTC 2020 - James Fehlig + +- qemu: Create multipath targets for PRs + a30078cb-qemu-create-mp-target.patch, + aeb909bf-qemu-multipath-fix.patch + bsc#1161883 + +------------------------------------------------------------------- +Mon Mar 16 08:42:10 UTC 2020 - Guillaume GARDET + +- Xen is not built for armv7 anymore, so do not use it for armv7 + ------------------------------------------------------------------- Thu Mar 5 04:09:43 UTC 2020 - James Fehlig diff --git a/libvirt.spec b/libvirt.spec index 2332e23..bd66a2c 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -59,8 +59,8 @@ # Set the OS / architecture specific special cases -# Xen is available only on x86_64, armv7 and aarch64 -%ifnarch x86_64 armv7hl aarch64 +# Xen is available only on x86_64 and aarch64 +%ifnarch x86_64 aarch64 %define with_libxl 0 %endif @@ -338,6 +338,8 @@ Source6: libvirtd-relocation-server.xml Source99: baselibs.conf Source100: %{name}-rpmlintrc # Upstream patches +Patch0: a30078cb-qemu-create-mp-target.patch +Patch1: aeb909bf-qemu-multipath-fix.patch # Patches pending upstream review Patch100: libxl-dom-reset.patch Patch101: network-don-t-use-dhcp-authoritative-on-static-netwo.patch @@ -365,6 +367,7 @@ Patch211: libvirt-suse-netcontrol.patch Patch212: lxc-wait-after-eth-del.patch Patch213: suse-libxl-disable-autoballoon.patch Patch214: suse-xen-ovmf-loaders.patch +Patch215: suse-bump-xen-version.patch # SLES-Only patches %if ! 0%{?is_opensuse} Patch400: virt-create-rootfs.patch @@ -871,6 +874,8 @@ libvirt plugin for NSS for translating domain names into IP addresses. %prep %setup -q +%patch0 -p1 +%patch1 -p1 %patch100 -p1 %patch101 -p1 %patch150 -p1 @@ -895,6 +900,7 @@ libvirt plugin for NSS for translating domain names into IP addresses. %patch212 -p1 %patch213 -p1 %patch214 -p1 +%patch215 -p1 %if ! 0%{?is_opensuse} %patch400 -p1 %endif diff --git a/suse-bump-xen-version.patch b/suse-bump-xen-version.patch new file mode 100644 index 0000000..4677842 --- /dev/null +++ b/suse-bump-xen-version.patch @@ -0,0 +1,79 @@ +Bump minimum supported Xen version to 4.9 + +There were no changes to the libxl API between 4.8 and 4.9, so +the LIBXL_API_VERSION is set to 0x040800. + +Note: xen.git commit c3999835df is needed in any Xen package where +this patch is expected to work. It is included in Xen 4.13, but would +need backporting to anything older. The dependency on xen.git commit +c3999835df makes it hard to upstream this patch. + +See bsc#1157490 and bsc#1167007 for more details +Index: libvirt-6.1.0/m4/virt-driver-libxl.m4 +=================================================================== +--- libvirt-6.1.0.orig/m4/virt-driver-libxl.m4 ++++ libvirt-6.1.0/m4/virt-driver-libxl.m4 +@@ -26,11 +26,11 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_LIBXL], [ + LIBXL_CFLAGS="" + LIBXL_FIRMWARE_DIR="" + LIBXL_EXECBIN_DIR="" +- LIBXL_API_VERSION="-DLIBXL_API_VERSION=0x040500" ++ LIBXL_API_VERSION="-DLIBXL_API_VERSION=0x040800" + + dnl search for libxl, aka libxenlight + old_with_libxl="$with_libxl" +- LIBVIRT_CHECK_PKG([LIBXL], [xenlight], [4.6.0]) ++ LIBVIRT_CHECK_PKG([LIBXL], [xenlight], [4.9.0]) + if test "x$with_libxl" = "xyes" ; then + LIBXL_FIRMWARE_DIR=$($PKG_CONFIG --variable xenfirmwaredir xenlight) + LIBXL_EXECBIN_DIR=$($PKG_CONFIG --variable libexec_bin xenlight) +Index: libvirt-6.1.0/src/libxl/libxl_conf.c +=================================================================== +--- libvirt-6.1.0.orig/src/libxl/libxl_conf.c ++++ libvirt-6.1.0/src/libxl/libxl_conf.c +@@ -1785,7 +1785,7 @@ int + libxlDriverConfigInit(libxlDriverConfigPtr cfg) + { + char ebuf[1024]; +- unsigned int free_mem; ++ uint64_t free_mem; + + if (virFileMakePath(cfg->logDir) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, +Index: libvirt-6.1.0/src/libxl/libxl_domain.c +=================================================================== +--- libvirt-6.1.0.orig/src/libxl/libxl_domain.c ++++ libvirt-6.1.0/src/libxl/libxl_domain.c +@@ -1006,8 +1006,8 @@ libxlDomainSetVcpuAffinities(libxlDriver + static int + libxlDomainFreeMem(libxl_ctx *ctx, libxl_domain_config *d_config) + { +- uint32_t needed_mem; +- uint32_t free_mem; ++ uint64_t needed_mem; ++ uint64_t free_mem; + int32_t target_mem; + int tries = 3; + int wait_secs = 10; +@@ -1401,7 +1401,7 @@ libxlDomainStart(libxlDriverPrivatePtr d + params.stream_version = restore_ver; + #endif + ret = libxl_domain_create_restore(cfg->ctx, &d_config, &domid, +- restore_fd, ¶ms, NULL, ++ restore_fd, -1, ¶ms, NULL, + &aop_console_how); + libxl_domain_restore_params_dispose(¶ms); + } +Index: libvirt-6.1.0/tests/libxlmock.c +=================================================================== +--- libvirt-6.1.0.orig/tests/libxlmock.c ++++ libvirt-6.1.0/tests/libxlmock.c +@@ -67,7 +67,7 @@ VIR_MOCK_IMPL_RET_ARGS(libxl_get_version + VIR_MOCK_STUB_RET_ARGS(libxl_get_free_memory, + int, 0, + libxl_ctx *, ctx, +- uint32_t *, memkb); ++ uint64_t *, memkb); + + VIR_MOCK_STUB_RET_ARGS(xc_interface_close, + int, 0,