import libvirt-8.0.0-5.4.module+el8.6.0+16370+bb85faee

This commit is contained in:
CentOS Sources 2022-09-13 03:41:25 -04:00 committed by Stepan Oksanichenko
parent 5b77fef41c
commit 24bf4e1110
13 changed files with 1034 additions and 1 deletions

View File

@ -0,0 +1,49 @@
From 2f3e89c97c7babc1d4da579eadf34979c8fc1725 Mon Sep 17 00:00:00 2001
Message-Id: <2f3e89c97c7babc1d4da579eadf34979c8fc1725@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 16:35:50 +0200
Subject: [PATCH] Add VIR_MIGRATE_ZEROCOPY flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The flag can be used to enable zero-copy mechanism for migrating memory
pages.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 8744beecb36600e773c8a8c4823db2bf4b3e262d)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Conflicts:
include/libvirt/libvirt-domain.h
- post-copy recovery not backported
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
include/libvirt/libvirt-domain.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 5f0a9b7572..792973ce2d 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -860,6 +860,14 @@ typedef enum {
*/
VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES = (1 << 18),
+ /* Use zero-copy mechanism for migrating memory pages. For QEMU/KVM this
+ * means QEMU will be temporarily allowed to lock all guest pages in host's
+ * memory, although only those that are queued for transfer will be locked
+ * at the same time.
+ *
+ * Since: 8.5.0
+ */
+ VIR_MIGRATE_ZEROCOPY = (1 << 20),
} virDomainMigrateFlags;
--
2.35.1

View File

@ -0,0 +1,91 @@
From b4469bda27e54a948f0d2750637226afc2b2be61 Mon Sep 17 00:00:00 2001
Message-Id: <b4469bda27e54a948f0d2750637226afc2b2be61@dist-git>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Wed, 11 May 2022 16:27:18 +0200
Subject: [PATCH] conf: Move virDomainObj::originalMemlock into
qemuDomainObjPrivate
Since v1.3.0-90-gafbe1d4c56 the original value of memlock limit
is stored inside virDomainObj struct directly (under
originalMemlock member). This is needless because the value is
used only inside QEMU driver and thus can reside in
qemuDomainObjPrivate struct.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 75df6d2c291c48d65c1e54dd93e3d2d3cb0712e7)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/conf/domain_conf.h | 3 ---
src/qemu/qemu_domain.c | 9 +++++----
src/qemu/qemu_domain.h | 3 +++
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 10af94e2e4..7e3255e41a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3030,9 +3030,6 @@ struct _virDomainObj {
int taint;
size_t ndeprecations;
char **deprecations;
-
- unsigned long long originalMemlock; /* Original RLIMIT_MEMLOCK, zero if no
- * restore will be required later */
};
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainObj, virObjectUnref);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 40fe9985e6..86d673dafa 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -9269,6 +9269,7 @@ int
qemuDomainAdjustMaxMemLock(virDomainObj *vm,
bool forceVFIO)
{
+ qemuDomainObjPrivate *priv = vm->privateData;
unsigned long long currentMemLock = 0;
unsigned long long desiredMemLock = 0;
@@ -9281,8 +9282,8 @@ qemuDomainAdjustMaxMemLock(virDomainObj *vm,
/* If this is the first time adjusting the limit, save the current
* value so that we can restore it once memory locking is no longer
* required */
- if (vm->originalMemlock == 0) {
- vm->originalMemlock = currentMemLock;
+ if (priv->originalMemlock == 0) {
+ priv->originalMemlock = currentMemLock;
}
} else {
/* If the limit is already high enough, we can assume
@@ -9295,8 +9296,8 @@ qemuDomainAdjustMaxMemLock(virDomainObj *vm,
} else {
/* Once memory locking is no longer required, we can restore the
* original, usually very low, limit */
- desiredMemLock = vm->originalMemlock;
- vm->originalMemlock = 0;
+ desiredMemLock = priv->originalMemlock;
+ priv->originalMemlock = 0;
}
if (desiredMemLock > 0 &&
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index e5046367e3..e9497d20de 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -241,6 +241,9 @@ struct _qemuDomainObjPrivate {
GSList *dbusVMStateIds;
/* true if -object dbus-vmstate was added */
bool dbusVMState;
+
+ unsigned long long originalMemlock; /* Original RLIMIT_MEMLOCK, zero if no
+ * restore will be required later */
};
#define QEMU_DOMAIN_PRIVATE(vm) \
--
2.35.1

View File

@ -0,0 +1,112 @@
From bfd8d181d45a22731ae5b1f05f3cb9488a2c7939 Mon Sep 17 00:00:00 2001
Message-Id: <bfd8d181d45a22731ae5b1f05f3cb9488a2c7939@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Jun 2022 13:23:29 +0200
Subject: [PATCH] domain_validate: Split out validation of disk startup policy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Move the code into 'virDomainDiskDefValidateStartupPolicy' which will be
later reused in the qemu driver.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 3603a18bcec18842cedecbd8329723062b87795c)
https://bugzilla.redhat.com/show_bug.cgi?id=2095758
https://bugzilla.redhat.com/show_bug.cgi?id=2109571
---
src/conf/domain_validate.c | 45 ++++++++++++++++++++++++--------------
src/conf/domain_validate.h | 2 ++
src/libvirt_private.syms | 1 +
3 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 452742e67c..bfff7339ef 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -598,6 +598,32 @@ virDomainDiskDefSourceLUNValidate(const virStorageSource *src)
}
+int
+virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk)
+{
+ if (disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_DEFAULT)
+ return 0;
+
+ if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("disk startupPolicy '%s' is not allowed for disk of '%s' type"),
+ virDomainStartupPolicyTypeToString(disk->startupPolicy),
+ virStorageTypeToString(disk->src->type));
+ return -1;
+ }
+
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
+ disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
+ disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainDiskDefValidate(const virDomainDef *def,
const virDomainDiskDef *disk)
@@ -775,23 +801,8 @@ virDomainDiskDefValidate(const virDomainDef *def,
return -1;
}
- if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
- if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
- virReportError(VIR_ERR_XML_ERROR,
- _("disk startupPolicy '%s' is not allowed for disk of '%s' type"),
- virDomainStartupPolicyTypeToString(disk->startupPolicy),
- virStorageTypeToString(disk->src->type));
- return -1;
- }
-
- if (disk->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
- disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
- disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy"));
- return -1;
- }
- }
+ if (virDomainDiskDefValidateStartupPolicy(disk) < 0)
+ return -1;
if (disk->wwn && !virValidateWWN(disk->wwn))
return -1;
diff --git a/src/conf/domain_validate.h b/src/conf/domain_validate.h
index 430d61fd3c..07b99195e3 100644
--- a/src/conf/domain_validate.h
+++ b/src/conf/domain_validate.h
@@ -41,4 +41,6 @@ int virDomainDeviceDefValidate(const virDomainDeviceDef *dev,
int virDomainDiskDefValidateSource(const virStorageSource *src);
+int virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk);
+
int virDomainDiskDefSourceLUNValidate(const virStorageSource *src);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2c42e2a5e8..5b7a056151 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -777,6 +777,7 @@ virDomainActualNetDefValidate;
virDomainDefValidate;
virDomainDeviceValidateAliasForHotplug;
virDomainDiskDefSourceLUNValidate;
+virDomainDiskDefValidateStartupPolicy;
# conf/interface_conf.h
--
2.35.1

View File

@ -0,0 +1,155 @@
From 7f5b89a15bfcd964c7f2b6ccbf3c03fd867f93b5 Mon Sep 17 00:00:00 2001
Message-Id: <7f5b89a15bfcd964c7f2b6ccbf3c03fd867f93b5@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 15:21:30 +0200
Subject: [PATCH] qemu: Add qemuDomainSetMaxMemLock helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
qemuDomainAdjustMaxMemLock combined computing the desired limit with
applying it. This patch separates the code to apply a memory locking
limit to a new qemuDomainSetMaxMemLock helper for better reusability.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit dff51c7f5760ded8235076f55d082fe4363f2f78)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 95 ++++++++++++++++++++++++++----------------
src/qemu/qemu_domain.h | 3 ++
2 files changed, 61 insertions(+), 37 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ee7d310903..a81789f194 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -9261,6 +9261,61 @@ qemuDomainGetMemLockLimitBytes(virDomainDef *def,
}
+/**
+ * qemuDomainSetMaxMemLock:
+ * @vm: domain
+ * @limit: the desired memory locking limit
+ * @origPtr: where to store (or load from) the original value of the limit
+ *
+ * Set the memory locking limit for @vm unless it's already big enough. If
+ * @origPtr is non-NULL, the original value of the limit will be store there
+ * and can be restored by calling this function with @limit == 0.
+ *
+ * Returns: 0 on success, -1 otherwise.
+ */
+int
+qemuDomainSetMaxMemLock(virDomainObj *vm,
+ unsigned long long limit,
+ unsigned long long *origPtr)
+{
+ unsigned long long current = 0;
+
+ if (virProcessGetMaxMemLock(vm->pid, &current) < 0)
+ return -1;
+
+ if (limit > 0) {
+ VIR_DEBUG("Requested memory lock limit: %llu", limit);
+ /* If the limit is already high enough, we can assume
+ * that some external process is taking care of managing
+ * process limits and we shouldn't do anything ourselves:
+ * we're probably running in a containerized environment
+ * where we don't have enough privilege anyway */
+ if (current >= limit) {
+ VIR_DEBUG("Current limit %llu is big enough", current);
+ return 0;
+ }
+
+ /* If this is the first time adjusting the limit, save the current
+ * value so that we can restore it once memory locking is no longer
+ * required */
+ if (origPtr && *origPtr == 0)
+ *origPtr = current;
+ } else {
+ /* Once memory locking is no longer required, we can restore the
+ * original, usually very low, limit. But only if we actually stored
+ * the original limit before. */
+ if (!origPtr || *origPtr == 0)
+ return 0;
+
+ limit = *origPtr;
+ *origPtr = 0;
+ VIR_DEBUG("Resetting memory lock limit back to %llu", limit);
+ }
+
+ return virProcessSetMaxMemLock(vm->pid, limit);
+}
+
+
/**
* qemuDomainAdjustMaxMemLock:
* @vm: domain
@@ -9282,43 +9337,9 @@ int
qemuDomainAdjustMaxMemLock(virDomainObj *vm,
bool forceVFIO)
{
- qemuDomainObjPrivate *priv = vm->privateData;
- unsigned long long currentMemLock = 0;
- unsigned long long desiredMemLock = 0;
-
- desiredMemLock = qemuDomainGetMemLockLimitBytes(vm->def, forceVFIO);
- if (virProcessGetMaxMemLock(vm->pid, &currentMemLock) < 0)
- return -1;
-
- if (desiredMemLock > 0) {
- if (currentMemLock < desiredMemLock) {
- /* If this is the first time adjusting the limit, save the current
- * value so that we can restore it once memory locking is no longer
- * required */
- if (priv->originalMemlock == 0) {
- priv->originalMemlock = currentMemLock;
- }
- } else {
- /* If the limit is already high enough, we can assume
- * that some external process is taking care of managing
- * process limits and we shouldn't do anything ourselves:
- * we're probably running in a containerized environment
- * where we don't have enough privilege anyway */
- desiredMemLock = 0;
- }
- } else {
- /* Once memory locking is no longer required, we can restore the
- * original, usually very low, limit */
- desiredMemLock = priv->originalMemlock;
- priv->originalMemlock = 0;
- }
-
- if (desiredMemLock > 0 &&
- virProcessSetMaxMemLock(vm->pid, desiredMemLock) < 0) {
- return -1;
- }
-
- return 0;
+ return qemuDomainSetMaxMemLock(vm,
+ qemuDomainGetMemLockLimitBytes(vm->def, forceVFIO),
+ &QEMU_DOMAIN_PRIVATE(vm)->originalMemlock);
}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index e9497d20de..6d1d23439a 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -789,6 +789,9 @@ int qemuDomainAdjustMaxMemLock(virDomainObj *vm,
bool forceVFIO);
int qemuDomainAdjustMaxMemLockHostdev(virDomainObj *vm,
virDomainHostdevDef *hostdev);
+int qemuDomainSetMaxMemLock(virDomainObj *vm,
+ unsigned long long limit,
+ unsigned long long *origPtr);
int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
const virDomainMemoryDef *mem);
--
2.35.1

View File

@ -0,0 +1,55 @@
From cbfe812a4affe5be7677bf28764b58dc7f99c969 Mon Sep 17 00:00:00 2001
Message-Id: <cbfe812a4affe5be7677bf28764b58dc7f99c969@dist-git>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Wed, 11 May 2022 16:37:27 +0200
Subject: [PATCH] qemu_domain: Format qemuDomainObjPrivate::originalMemlock
Now that qemuDomainObjPrivate struct gained new member format it
into XML and parse it so that the value is preserved across
daemon restarts.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 21aec91790ae14d24512856b20cff49764ede637)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 86d673dafa..ee7d310903 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2383,6 +2383,12 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf,
if (qemuDomainObjPrivateXMLFormatBackups(buf, vm) < 0)
return -1;
+ if (priv->originalMemlock > 0) {
+ virBufferAsprintf(buf,
+ "<originalMemlock>%llu</originalMemlock>\n",
+ priv->originalMemlock);
+ }
+
return 0;
}
@@ -3104,6 +3110,13 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
priv->memPrealloc = virXPathBoolean("boolean(./memPrealloc)", ctxt) == 1;
+ if (virXPathULongLong("string(./originalMemlock)",
+ ctxt, &priv->originalMemlock) == -2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse original memlock size"));
+ goto error;
+ }
+
return 0;
error:
--
2.35.1

View File

@ -0,0 +1,120 @@
From 34dc905251ca0f00d92e8419adc63580c6266394 Mon Sep 17 00:00:00 2001
Message-Id: <34dc905251ca0f00d92e8419adc63580c6266394@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 16:37:31 +0200
Subject: [PATCH] qemu_migration: Implement VIR_MIGRATE_ZEROCOPY flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves: https://gitlab.com/libvirt/libvirt/-/issues/306
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit d375993ab314a41bca7ef6c846e07afc18c37774)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Conflicts:
src/qemu/qemu_migration.c
src/qemu/qemu_migration.h
- post-copy recovery not bacported
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_migration.c | 21 +++++++++++++++++++++
src/qemu/qemu_migration.h | 1 +
src/qemu/qemu_migration_params.c | 6 ++++++
src/qemu/qemu_migration_params.h | 1 +
4 files changed, 29 insertions(+)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 01102c4300..11f87296d6 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2366,6 +2366,12 @@ qemuMigrationSrcBeginPhase(virQEMUDriver *driver,
return NULL;
}
+ if (flags & VIR_MIGRATE_ZEROCOPY && !(flags & VIR_MIGRATE_PARALLEL)) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("zero-copy is only available for parallel migration"));
+ return NULL;
+ }
+
if (flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC)) {
if (flags & VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES &&
!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) {
@@ -4137,6 +4143,21 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
migParams) < 0)
goto error;
+ if (flags & VIR_MIGRATE_ZEROCOPY) {
+ /* Zero-copy requires pages in transfer to be locked in host memory.
+ * Unfortunately, we have no reliable way of computing how many pages
+ * will need to be locked at the same time. Thus we set the limit to
+ * the whole guest memory and reset it back once migration is done. */
+ unsigned long long limit;
+
+ if (virMemoryLimitIsSet(vm->def->mem.hard_limit))
+ limit = vm->def->mem.hard_limit;
+ else
+ limit = virDomainDefGetMemoryTotal(vm->def);
+
+ if (qemuDomainSetMaxMemLock(vm, limit << 10, &priv->preMigrationMemlock) < 0)
+ goto error;
+ }
if (storageMigration) {
if (mig->nbd) {
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index b233358a51..6f737f7b4c 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -60,6 +60,7 @@
VIR_MIGRATE_TLS | \
VIR_MIGRATE_PARALLEL | \
VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES | \
+ VIR_MIGRATE_ZEROCOPY | \
0)
/* All supported migration parameters and their types. */
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index 7b225fdf4b..c985583861 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -96,6 +96,7 @@ VIR_ENUM_IMPL(qemuMigrationCapability,
"multifd",
"dirty-bitmaps",
"return-path",
+ "zero-copy-send",
);
@@ -177,6 +178,11 @@ static const qemuMigrationParamsFlagMapItem qemuMigrationParamsFlagMap[] = {
VIR_MIGRATE_TUNNELLED,
QEMU_MIGRATION_CAP_RETURN_PATH,
QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION},
+
+ {QEMU_MIGRATION_FLAG_REQUIRED,
+ VIR_MIGRATE_ZEROCOPY,
+ QEMU_MIGRATION_CAP_ZERO_COPY_SEND,
+ QEMU_MIGRATION_SOURCE},
};
/* Translation from VIR_MIGRATE_PARAM_* typed parameters to
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index b4de8dda7b..caa5e47f0f 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -41,6 +41,7 @@ typedef enum {
QEMU_MIGRATION_CAP_MULTIFD,
QEMU_MIGRATION_CAP_BLOCK_DIRTY_BITMAPS,
QEMU_MIGRATION_CAP_RETURN_PATH,
+ QEMU_MIGRATION_CAP_ZERO_COPY_SEND,
QEMU_MIGRATION_CAP_LAST
} qemuMigrationCapability;
--
2.35.1

View File

@ -0,0 +1,138 @@
From 7cbfdb081de6e4eb684447ba48869082df798419 Mon Sep 17 00:00:00 2001
Message-Id: <7cbfdb081de6e4eb684447ba48869082df798419@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 16:12:02 +0200
Subject: [PATCH] qemu_migration: Restore original memory locking limit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For RDMA migration we update memory locking limit, but never set it back
once migration finishes (on the destination host) or aborts (on the
source host).
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit d4d3bb813031275c2c7cf72724b83c97ce82ab7a)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Conflicts:
src/qemu/qemu_migration.c
- post-copy resovery not backported
The original 8.7.0 backport contained a bug which was later fixed by
"qemu_migration: Fix restoring memlock limit on destination". This
backport includes the follow up fix squashed in.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 12 ++++++++++++
src/qemu/qemu_domain.h | 3 +++
src/qemu/qemu_migration.c | 11 +++++++++--
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index a81789f194..c24d1e4d53 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2389,6 +2389,11 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf,
priv->originalMemlock);
}
+ if (priv->preMigrationMemlock > 0) {
+ virBufferAsprintf(buf, "<preMigrationMemlock>%llu</preMigrationMemlock>\n",
+ priv->preMigrationMemlock);
+ }
+
return 0;
}
@@ -3117,6 +3122,13 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
goto error;
}
+ if (virXPathULongLong("string(./preMigrationMemlock)", ctxt,
+ &priv->preMigrationMemlock) == -2) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to parse pre-migration memlock limit"));
+ return -1;
+ }
+
return 0;
error:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 6d1d23439a..d6e8a7a0fb 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -146,6 +146,9 @@ struct _qemuDomainObjPrivate {
int nbdPort; /* Port used for migration with NBD */
unsigned short migrationPort;
int preMigrationState;
+ unsigned long long preMigrationMemlock; /* Original RLIMIT_MEMLOCK in case
+ it was changed for the current
+ migration job. */
virChrdevs *devs;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 10338f8e87..01102c4300 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2974,7 +2974,8 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver,
if (STREQ_NULLABLE(protocol, "rdma") &&
vm->def->mem.hard_limit > 0 &&
- qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) {
+ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10,
+ &priv->preMigrationMemlock) < 0) {
goto stopjob;
}
@@ -3451,6 +3452,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriver *driver,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
virObjectEventStateQueue(driver->domainEventState, event);
qemuDomainEventEmitJobCompleted(driver, vm);
+ priv->preMigrationMemlock = 0;
} else {
virErrorPtr orig_err;
int reason;
@@ -3471,6 +3473,7 @@ qemuMigrationSrcConfirmPhase(virQEMUDriver *driver,
qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
jobPriv->migParams, priv->job.apiFlags);
+ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock);
qemuDomainSaveStatus(vm);
}
@@ -4224,7 +4227,8 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
case MIGRATION_DEST_HOST:
if (STREQ(spec->dest.host.protocol, "rdma") &&
vm->def->mem.hard_limit > 0 &&
- qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) {
+ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10,
+ &priv->preMigrationMemlock) < 0) {
goto exit_monitor;
}
rc = qemuMonitorMigrateToHost(priv->mon, migrate_flags,
@@ -5408,6 +5412,7 @@ qemuMigrationSrcPerformPhase(virQEMUDriver *driver,
if (ret < 0) {
qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
jobPriv->migParams, priv->job.apiFlags);
+ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock);
qemuMigrationJobFinish(driver, vm);
} else {
qemuMigrationJobContinue(vm);
@@ -5869,6 +5874,8 @@ qemuMigrationDstFinish(virQEMUDriver *driver,
*/
if (inPostCopy)
g_clear_pointer(&priv->job.completed, qemuDomainJobInfoFree);
+
+ qemuDomainSetMaxMemLock(vm, 0, &priv->preMigrationMemlock);
}
qemuMigrationParamsReset(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN,
--
2.35.1

View File

@ -0,0 +1,53 @@
From ad3f1dceac21369b9c18b6032a4ff859dc79bbc7 Mon Sep 17 00:00:00 2001
Message-Id: <ad3f1dceac21369b9c18b6032a4ff859dc79bbc7@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 09:04:04 +0200
Subject: [PATCH] qemu_migration: Use qemuDomainSetMaxMemLock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This helper will not try to set the limit if it is already big enough,
which may be useful when libvirt daemon is running in a containerized
environment and is not allowed to change memory locking limit.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 22ee8cbf090c45f999b76e3f8dc7a45065fc9edf)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Conflicts:
src/qemu/qemu_migration.c
- refactoring for post-copy recovery not backported
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_migration.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 2635ef1162..10338f8e87 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2974,7 +2974,7 @@ qemuMigrationDstPrepareAny(virQEMUDriver *driver,
if (STREQ_NULLABLE(protocol, "rdma") &&
vm->def->mem.hard_limit > 0 &&
- virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
+ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) {
goto stopjob;
}
@@ -4224,7 +4224,7 @@ qemuMigrationSrcRun(virQEMUDriver *driver,
case MIGRATION_DEST_HOST:
if (STREQ(spec->dest.host.protocol, "rdma") &&
vm->def->mem.hard_limit > 0 &&
- virProcessSetMaxMemLock(vm->pid, vm->def->mem.hard_limit << 10) < 0) {
+ qemuDomainSetMaxMemLock(vm, vm->def->mem.hard_limit << 10, NULL) < 0) {
goto exit_monitor;
}
rc = qemuMonitorMigrateToHost(priv->mon, migrate_flags,
--
2.35.1

View File

@ -0,0 +1,52 @@
From 4c57d8399b86c07ee0b1bafd2f8bf0ba10ff384f Mon Sep 17 00:00:00 2001
Message-Id: <4c57d8399b86c07ee0b1bafd2f8bf0ba10ff384f@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Jun 2022 13:13:48 +0200
Subject: [PATCH] virDomainDiskDefValidate: Improve error messages for
'startupPolicy' checks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Remove linebreak and mention the attribute name. Also prepare the error
messages for future by substituting the type of offending access.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit 9a480737c8adf92c332aa850c5269191ceb04eb9)
https://bugzilla.redhat.com/show_bug.cgi?id=2095758
https://bugzilla.redhat.com/show_bug.cgi?id=2109571
---
src/conf/domain_validate.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index a4271f1247..452742e67c 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -778,9 +778,9 @@ virDomainDiskDefValidate(const virDomainDef *def,
if (disk->startupPolicy != VIR_DOMAIN_STARTUP_POLICY_DEFAULT) {
if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
virReportError(VIR_ERR_XML_ERROR,
- _("Setting disk %s is not allowed for "
- "disk of network type"),
- virDomainStartupPolicyTypeToString(disk->startupPolicy));
+ _("disk startupPolicy '%s' is not allowed for disk of '%s' type"),
+ virDomainStartupPolicyTypeToString(disk->startupPolicy),
+ virStorageTypeToString(disk->src->type));
return -1;
}
@@ -788,8 +788,7 @@ virDomainDiskDefValidate(const virDomainDef *def,
disk->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE) {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("Setting disk 'requisite' is allowed only for "
- "cdrom or floppy"));
+ _("disk startupPolicy 'requisite' is allowed only for cdrom or floppy"));
return -1;
}
}
--
2.35.1

View File

@ -0,0 +1,43 @@
From a5cdca9995a05ac45e882ad3e1ca1e4ab53a2c34 Mon Sep 17 00:00:00 2001
Message-Id: <a5cdca9995a05ac45e882ad3e1ca1e4ab53a2c34@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Jun 2022 14:07:47 +0200
Subject: [PATCH] virDomainDiskDefValidateStartupPolicy: Validate disk type
better
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Our startup policy checkers work only for local paths, so disk sources
such as NVMe, or vhost-user can't be used with startup policy.
Unfortunately the validation did not catch these cases. Fix it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit b90d0f0a1e4ee52c828fb683c14c14e241e6fcbb)
https://bugzilla.redhat.com/show_bug.cgi?id=2095758
https://bugzilla.redhat.com/show_bug.cgi?id=2109571
---
src/conf/domain_validate.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index bfff7339ef..55759af9f8 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -604,7 +604,10 @@ virDomainDiskDefValidateStartupPolicy(const virDomainDiskDef *disk)
if (disk->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_DEFAULT)
return 0;
- if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) {
+ /* We want to allow any startup policy for un-translated _TYPE_VOLUME disks.
+ * virStorageSourceGetActualType returns _TYPE_VOLUME in such case */
+ if (virStorageSourceGetActualType(disk->src) != VIR_STORAGE_TYPE_VOLUME &&
+ !virStorageSourceIsLocalStorage(disk->src)) {
virReportError(VIR_ERR_XML_ERROR,
_("disk startupPolicy '%s' is not allowed for disk of '%s' type"),
virDomainStartupPolicyTypeToString(disk->startupPolicy),
--
2.35.1

View File

@ -0,0 +1,57 @@
From d56c0a4b1b57d9547d40088b6787d7503c09e2b9 Mon Sep 17 00:00:00 2001
Message-Id: <d56c0a4b1b57d9547d40088b6787d7503c09e2b9@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 14 Jun 2022 14:21:33 +0200
Subject: [PATCH] virDomainDiskTranslateSourcePool: Fix check of
'startupPolicy' definition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The check was historically done only for _TYPE_VOLUME disks, but
refactors to allow _TYPE_VOLUME disks in the backing chain caused a
regression where we'd reject startupPolicy also for _TYPE_BLOCK disks
which historically worked well.
Fix it by using the 'virDomainDiskDefValidateStartupPolicy' helper and
use it only when the top level image is a _TYPE_VOLUME as in other cases
it was already validated. This also allows _TYPE_BLOCK volumes to use
startup policy.
Fixes: 37f01262eed9f37dd5eb7de8b83edd2fea741054
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2095758
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit ed8984306e1cd44c424fda3ed412a4177dd7b84d)
https://bugzilla.redhat.com/show_bug.cgi?id=2109571
---
src/conf/domain_conf.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 805a15848e..92510973e6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31311,13 +31311,13 @@ virDomainDiskTranslateSourcePool(virDomainDiskDef *def)
if (virDomainStorageSourceTranslateSourcePool(n, conn) < 0)
return -1;
- }
- if (def->startupPolicy != 0 &&
- virStorageSourceGetActualType(def->src) != VIR_STORAGE_TYPE_FILE) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("'startupPolicy' is only valid for 'file' type volume"));
- return -1;
+ /* The validity of 'startupPolicy' setting is checked only for the top
+ * level image. For any other subsequent images we honour it only if
+ * possible */
+ if (n == def->src &&
+ virDomainDiskDefValidateStartupPolicy(def) < 0)
+ return -1;
}
return 0;
--
2.35.1

View File

@ -0,0 +1,80 @@
From eb87264dc41a7147fb88fdc4d666ef8d0e9bb882 Mon Sep 17 00:00:00 2001
Message-Id: <eb87264dc41a7147fb88fdc4d666ef8d0e9bb882@dist-git>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Wed, 22 Jun 2022 16:36:53 +0200
Subject: [PATCH] virsh: Add support for VIR_MIGRATE_ZEROCOPY flag
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
(cherry picked from commit efa3baeae70fbdf4ab032ca485cb9272ee96bd50)
https://bugzilla.redhat.com/show_bug.cgi?id=2117272
Conflicts:
docs/manpages/virsh.rst
tools/virsh-domain.c
- post-copy recovery not backported
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
docs/manpages/virsh.rst | 8 +++++++-
tools/virsh-domain.c | 7 +++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index dd534c10cb..d24e7774a6 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -3225,7 +3225,8 @@ migrate
migrate [--live] [--offline] [--direct] [--p2p [--tunnelled]]
[--persistent] [--undefinesource] [--suspend] [--copy-storage-all]
[--copy-storage-inc] [--change-protection] [--unsafe] [--verbose]
- [--rdma-pin-all] [--abort-on-error] [--postcopy] [--postcopy-after-precopy]
+ [--rdma-pin-all] [--abort-on-error] [--postcopy]
+ [--postcopy-after-precopy] [--zerocopy]
domain desturi [migrateuri] [graphicsuri] [listen-address] [dname]
[--timeout seconds [--timeout-suspend | --timeout-postcopy]]
[--xml file] [--migrate-disks disk-list] [--disks-port port]
@@ -3298,6 +3299,11 @@ high (and thus allowing the domain to lock most of the host's memory). Doing so
may be dangerous to both the domain and the host itself since the host's kernel
may run out of memory.
+*--zerocopy* requests zero-copy mechanism to be used for migrating memory pages.
+For QEMU/KVM this means QEMU will be temporarily allowed to lock all guest
+pages in host's memory, although only those that are queued for transfer will
+be locked at the same time.
+
``Note``: Individual hypervisors usually do not support all possible types of
migration. For example, QEMU does not support direct migration.
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index b56f6a90f5..c5bade1dbf 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -10730,6 +10730,10 @@ static const vshCmdOptDef opts_migrate[] = {
.type = VSH_OT_BOOL,
.help = N_("automatically switch to post-copy migration after one pass of pre-copy")
},
+ {.name = "zerocopy",
+ .type = VSH_OT_BOOL,
+ .help = N_("use zero-copy mechanism for migrating memory pages")
+ },
{.name = "migrateuri",
.type = VSH_OT_STRING,
.completer = virshCompleteEmpty,
@@ -11133,6 +11137,9 @@ doMigrate(void *opaque)
if (vshCommandOptBool(cmd, "postcopy"))
flags |= VIR_MIGRATE_POSTCOPY;
+ if (vshCommandOptBool(cmd, "zerocopy"))
+ flags |= VIR_MIGRATE_ZEROCOPY;
+
if (vshCommandOptBool(cmd, "tls"))
flags |= VIR_MIGRATE_TLS;
--
2.35.1

View File

@ -210,7 +210,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 8.0.0
Release: 5.2%{?dist}%{?extra_release}
Release: 5.4%{?dist}%{?extra_release}
License: LGPLv2+
URL: https://libvirt.org/
@ -250,6 +250,18 @@ Patch27: libvirt-cpu_x86-Consolidate-signature-match-in-x86DecodeUseCandidate.pa
Patch28: libvirt-cpu_x86-Refactor-feature-list-comparison-in-x86DecodeUseCandidate.patch
Patch29: libvirt-cpu_x86-Penalize-disabled-features-when-computing-CPU-model.patch
Patch30: libvirt-cpu_x86-Ignore-enabled-features-for-input-models-in-x86DecodeUseCandidate.patch
Patch31: libvirt-virDomainDiskDefValidate-Improve-error-messages-for-startupPolicy-checks.patch
Patch32: libvirt-domain_validate-Split-out-validation-of-disk-startup-policy.patch
Patch33: libvirt-virDomainDiskDefValidateStartupPolicy-Validate-disk-type-better.patch
Patch34: libvirt-virDomainDiskTranslateSourcePool-Fix-check-of-startupPolicy-definition.patch
Patch35: libvirt-conf-Move-virDomainObj-originalMemlock-into-qemuDomainObjPrivate.patch
Patch36: libvirt-qemu_domain-Format-qemuDomainObjPrivate-originalMemlock.patch
Patch37: libvirt-qemu-Add-qemuDomainSetMaxMemLock-helper.patch
Patch38: libvirt-qemu_migration-Use-qemuDomainSetMaxMemLock.patch
Patch39: libvirt-qemu_migration-Restore-original-memory-locking-limit.patch
Patch40: libvirt-Add-VIR_MIGRATE_ZEROCOPY-flag.patch
Patch41: libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch
Patch42: libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch
Requires: libvirt-daemon = %{version}-%{release}
Requires: libvirt-daemon-config-network = %{version}-%{release}
@ -2123,6 +2135,22 @@ exit 0
%changelog
* Thu Aug 18 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-5.4.el8
- conf: Move virDomainObj::originalMemlock into qemuDomainObjPrivate (rhbz#2117272)
- qemu_domain: Format qemuDomainObjPrivate::originalMemlock (rhbz#2117272)
- qemu: Add qemuDomainSetMaxMemLock helper (rhbz#2117272)
- qemu_migration: Use qemuDomainSetMaxMemLock (rhbz#2117272)
- qemu_migration: Restore original memory locking limit (rhbz#2117272)
- Add VIR_MIGRATE_ZEROCOPY flag (rhbz#2117272)
- virsh: Add support for VIR_MIGRATE_ZEROCOPY flag (rhbz#2117272)
- qemu_migration: Implement VIR_MIGRATE_ZEROCOPY flag (rhbz#2117272)
* Fri Jul 29 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-5.3.el8
- virDomainDiskDefValidate: Improve error messages for 'startupPolicy' checks (rhbz#2109571)
- domain_validate: Split out validation of disk startup policy (rhbz#2109571)
- virDomainDiskDefValidateStartupPolicy: Validate disk type better (rhbz#2109571)
- virDomainDiskTranslateSourcePool: Fix check of 'startupPolicy' definition (rhbz#2109571)
* Tue May 17 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-5.2.el8
- cpu_map: Disable cpu64-rhel* for host-model and baseline (rhbz#2084030)
- cputest: Drop some old artificial baseline tests (rhbz#2084030)