Userfaultfd is by default allowed only for privileged processes. Since libvirt runs QEMU unprivileged, we need to enable unprivileged access to userfaultfd before starting post-copy migration. Rather than providing a static sysctl configuration file, we set the sysctl knob in runtime once post-copy migration is requested. This way unprivileged_userfaultfd is only enabled once actually used. https://bugzilla.redhat.com/show_bug.cgi?id=1945420 Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- Notes: Version 2: - setting unprivileged_userfaultfd only when it is not already enabled - virReportSystemError replaced with VIR_WARN src/qemu/qemu_migration_params.c | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index dbc3219826..9ba4811242 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -804,6 +804,41 @@ qemuMigrationCapsToJSON(virBitmap *caps, } +/** + * qemuMigrationParamsEnableUserfaultfd + * + * Try to enable unprivileged userfaultfd unless it's missing or already + * enabled. Only a warning is logged when we cannot enable it, QEMU will + * report an error when enabling post-copy migration capability. + */ +static void +qemuMigrationParamsEnableUserfaultfd(void) +{ + const char *sysctl = "/proc/sys/vm/unprivileged_userfaultfd"; + g_autofree char *buf = NULL; + + if (!virFileExists(sysctl)) + return; + + if (virFileReadAll(sysctl, 10, &buf) < 0) { + VIR_WARN("Cannot read unprivileged userfaultfd state"); + return; + } + + if (STREQ(buf, "1\n")) { + VIR_DEBUG("Unprivileged userfaultfd already enabled"); + return; + } + + VIR_DEBUG("Enabling unprivileged userfaultfd for post-copy migration"); + + if (virFileWriteStr(sysctl, "1", 0) < 0) { + VIR_WARN("Failed to enable unprivileged userfaultfd: %s", + g_strerror(errno)); + } +} + + /** * qemuMigrationParamsApply * @driver: qemu driver @@ -839,6 +874,13 @@ qemuMigrationParamsApply(virQEMUDriver *driver, goto cleanup; } } else { + /* userfaultfd may only be enabled for privileged processes by default, + * we need to make sure QEMU can use it before enabling post-copy + * migration */ + if (virBitmapIsBitSet(priv->migrationCaps, QEMU_MIGRATION_CAP_POSTCOPY) && + virBitmapIsBitSet(migParams->caps, QEMU_MIGRATION_CAP_POSTCOPY)) + qemuMigrationParamsEnableUserfaultfd(); + if (!(caps = qemuMigrationCapsToJSON(priv->migrationCaps, migParams->caps))) goto cleanup; -- 2.34.1