diff --git a/hotpatch-virsh-support-autoload-mode.patch b/hotpatch-virsh-support-autoload-mode.patch new file mode 100644 index 0000000000000000000000000000000000000000..2c95db6e60c039fc6e7911f39ff0e4484d8ab696 --- /dev/null +++ b/hotpatch-virsh-support-autoload-mode.patch @@ -0,0 +1,302 @@ +From 3be8bb571d13795c2824dd6d2089035a1be6cf57 Mon Sep 17 00:00:00 2001 +From: jiang-dawei15 +Date: Wed, 26 Jan 2022 15:18:10 +0800 +Subject: [PATCH] hotpatch: virsh support autoload mode + +--- + include/libvirt/libvirt-domain.h | 1 + + src/qemu/qemu_conf.c | 9 +++ + src/qemu/qemu_conf.h | 1 + + src/qemu/qemu_driver.c | 5 ++ + src/qemu/qemu_hotpatch.c | 122 +++++++++++++++++++++++++++++++ + src/qemu/qemu_hotpatch.h | 3 + + src/qemu/qemu_process.c | 6 ++ + tools/virsh-domain.c | 5 +- + 8 files changed, 150 insertions(+), 2 deletions(-) + +diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h +index 2d6432cab2..4ab0c9c0b2 100644 +--- a/include/libvirt/libvirt-domain.h ++++ b/include/libvirt/libvirt-domain.h +@@ -4997,6 +4997,7 @@ typedef enum { + VIR_DOMAIN_HOTPATCH_APPLY, /* Apply hotpatch */ + VIR_DOMAIN_HOTPATCH_UNAPPLY, /* Unapply hotpatch */ + VIR_DOMAIN_HOTPATCH_QUERY, /* Query hotpatch */ ++ VIR_DOMAIN_HOTPATCH_AUTOLOAD, /* Autoload hotpatch */ + + # ifdef VIR_ENUM_SENTINELS + VIR_DOMAIN_HOTPATCH_LAST +diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c +index 809e8fe526..bd96ccb78e 100644 +--- a/src/qemu/qemu_conf.c ++++ b/src/qemu/qemu_conf.c +@@ -1006,6 +1006,12 @@ virQEMUDriverConfigLoadCapsFiltersEntry(virQEMUDriverConfigPtr cfg, + return 0; + } + ++static int ++virQEMUDriverConfigLoadHotpatchPathEntry(virQEMUDriverConfigPtr cfg, ++ virConfPtr conf) ++{ ++ return virConfGetValueString(conf, "hotpatch_path", &cfg->hotpatchPath); ++} + + int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, + const char *filename, +@@ -1078,6 +1084,9 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg, + if (virQEMUDriverConfigLoadCapsFiltersEntry(cfg, conf) < 0) + return -1; + ++ if (virQEMUDriverConfigLoadHotpatchPathEntry(cfg, conf) < 0) ++ return -1; ++ + return 0; + } + +diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h +index 14f9b9e81e..f0124a0fe2 100644 +--- a/src/qemu/qemu_conf.h ++++ b/src/qemu/qemu_conf.h +@@ -220,6 +220,7 @@ struct _virQEMUDriverConfig { + gid_t swtpm_group; + + char **capabilityfilters; ++ char *hotpatchPath; + }; + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virQEMUDriverConfig, virObjectUnref); +diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c +index 2b24881f75..37b2c4a2da 100644 +--- a/src/qemu/qemu_driver.c ++++ b/src/qemu/qemu_driver.c +@@ -23186,6 +23186,7 @@ qemuDomainHotpatchManage(virDomainPtr domain, + virQEMUDriverPtr driver = domain->conn->privateData; + char *ret = NULL; + size_t len; ++ g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + + virCheckFlags(0, NULL); + +@@ -23214,6 +23215,10 @@ qemuDomainHotpatchManage(virDomainPtr domain, + ret = qemuDomainHotpatchQuery(vm); + break; + ++ case VIR_DOMAIN_HOTPATCH_AUTOLOAD: ++ ret = qemuDomainHotpatchAutoload(vm, cfg->hotpatchPath); ++ break; ++ + default: + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Unknow hotpatch action")); +diff --git a/src/qemu/qemu_hotpatch.c b/src/qemu/qemu_hotpatch.c +index 03e63c1341..02f511cc38 100644 +--- a/src/qemu/qemu_hotpatch.c ++++ b/src/qemu/qemu_hotpatch.c +@@ -25,6 +25,8 @@ + #include "virerror.h" + #include "virfile.h" + #include "virlog.h" ++#include "virbuffer.h" ++#include "virstring.h" + #include "vircommand.h" + #include "qemu/qemu_domain.h" + #include "qemu_hotpatch.h" +@@ -32,6 +34,7 @@ + #define LIBCARE_CTL "libcare-ctl" + #define LIBCARE_ERROR_NUMBER 255 + #define MAX_PATCHID_LEN 8 ++#define MAX_FILE_SIZE (1024*1024) + + #define VIR_FROM_THIS VIR_FROM_QEMU + +@@ -204,3 +207,122 @@ qemuDomainHotpatchUnapply(virDomainObjPtr vm, + VIR_FREE(output); + return NULL; + } ++ ++char * ++qemuDomainHotpatchAutoload(virDomainObjPtr vm, char *hotpatch_path) ++{ ++ VIR_AUTOSTRINGLIST applied_patches = NULL; ++ VIR_AUTOSTRINGLIST lines = NULL; ++ g_autofree char *applied_patch = NULL; ++ g_autofree char *libvirtd_conf = NULL; ++ g_autofree char *patch_conf = NULL; ++ g_autofree char *buf = NULL; ++ char *ret = NULL; ++ int i, j, len; ++ ++ if (hotpatch_path == NULL) { ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("Invalid hotpatch path.")); ++ return NULL; ++ } ++ ++ /* get hotpatch info from Patch.conf */ ++ patch_conf = g_strdup_printf("%s/Patch.conf", hotpatch_path); ++ if ((len = virFileReadAll(patch_conf, MAX_FILE_SIZE, &buf)) < 0) { ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("Failed to read Patch.conf file.")); ++ return NULL; ++ } ++ if (len > 0) ++ buf[len-1] = '\0'; ++ ++ lines = virStringSplit(buf, "\n", 0); ++ if (!lines) ++ return NULL; ++ ++ /* get domain hotpatch infomation */ ++ applied_patch = qemuDomainHotpatchQuery(vm); ++ if (!applied_patch) ++ return NULL; ++ ++ applied_patches = virStringSplit(applied_patch, "\n", 0); ++ if (!applied_patches) ++ return NULL; ++ ++ /* load all hotpatch which are listed in Patch.conf one by one */ ++ for (i = 0; lines[i] != NULL; i++) { ++ VIR_AUTOSTRINGLIST patch_info = NULL; ++ g_autofree char *kpatch_dir = NULL; ++ g_autofree char *file_path = NULL; ++ struct dirent *de; ++ DIR *dh; ++ int direrr; ++ ++ if (!strstr(lines[i], "QEMU-")) ++ continue; ++ ++ patch_info = virStringSplit(lines[i], " ", 0); ++ if (!patch_info) ++ continue; ++ ++ /* skip already applied patch */ ++ if (strstr(applied_patch, patch_info[2])) ++ continue; ++ ++ /* get the kpatch file name */ ++ kpatch_dir = g_strdup_printf("%s/%s", hotpatch_path, patch_info[1]); ++ if (!kpatch_dir || !virFileExists(kpatch_dir)) ++ return NULL; ++ ++ if (virDirOpen(&dh, kpatch_dir) < 0) ++ return NULL; ++ if ((direrr = virDirRead(dh, &de, kpatch_dir)) > 0) { ++ GStatBuf sb; ++ ++ file_path = g_strdup_printf("%s/%s", kpatch_dir, de->d_name); ++ if (g_lstat(file_path, &sb) < 0) { ++ virReportSystemError(errno, _("Cannot access '%s'"), ++ file_path); ++ VIR_DIR_CLOSE(dh); ++ return NULL; ++ } ++ } ++ VIR_DIR_CLOSE(dh); ++ ++ if (qemuDomainHotpatchApply(vm, file_path) == NULL) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to apply the hotpatch.")); ++ return NULL; ++ } ++ } ++ ++ /* unload the hotpatch which are not listed in Patch.conf */ ++ for (i = 0; applied_patches[i] != NULL; i++) { ++ const char *patch_id = NULL; ++ bool is_need_unload = true; ++ ++ if (!strstr(applied_patches[i], "Patch id")) ++ continue; ++ ++ patch_id = strstr(applied_patches[i], ":") + 1; ++ virSkipSpaces(&patch_id); ++ ++ for (j = 0; lines[j] != NULL; j++) { ++ if (!strstr(lines[j], "QEMU-")) ++ continue; ++ if (strstr(lines[j], patch_id)) { ++ is_need_unload = false; ++ break; ++ } ++ } ++ if (is_need_unload == true) ++ if (qemuDomainHotpatchUnapply(vm, patch_id) == NULL) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("failed to unapply the hotpatch.")); ++ return NULL; ++ } ++ } ++ ++ ret = g_strdup_printf("Hotpatch autoload successfully.\n"); ++ return ret; ++} +diff --git a/src/qemu/qemu_hotpatch.h b/src/qemu/qemu_hotpatch.h +index 4c84a57950..8e0bfe348a 100644 +--- a/src/qemu/qemu_hotpatch.h ++++ b/src/qemu/qemu_hotpatch.h +@@ -34,3 +34,6 @@ qemuDomainHotpatchApply(virDomainObjPtr vm, + char * + qemuDomainHotpatchUnapply(virDomainObjPtr vm, + const char *id); ++ ++char * ++qemuDomainHotpatchAutoload(virDomainObjPtr vm, char *path_config); +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 818a72d8f9..24dd9f052c 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -59,6 +59,7 @@ + #include "qemu_firmware.h" + #include "qemu_backup.h" + #include "qemu_dbus.h" ++#include "qemu_hotpatch.h" + + #include "cpu/cpu.h" + #include "cpu/cpu_x86.h" +@@ -6684,6 +6685,7 @@ qemuProcessLaunch(virConnectPtr conn, + g_autoptr(virQEMUDriverConfig) cfg = NULL; + size_t nnicindexes = 0; + g_autofree int *nicindexes = NULL; ++ g_autofree char *autoLoadStatus = NULL; + size_t i; + + VIR_DEBUG("conn=%p driver=%p vm=%p name=%s if=%d asyncJob=%d " +@@ -6993,6 +6995,10 @@ qemuProcessLaunch(virConnectPtr conn, + qemuProcessAutoDestroyAdd(driver, vm, conn) < 0) + goto cleanup; + ++ /* Autoload hotpatch */ ++ if ((autoLoadStatus = qemuDomainHotpatchAutoload(vm, cfg->hotpatchPath)) == NULL) { ++ VIR_WARN("Failed to autoload the hotpatch for %s.", vm->def->name); ++ } + ret = 0; + + cleanup: +diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c +index 813be4a0db..b5375ebd3e 100644 +--- a/tools/virsh-domain.c ++++ b/tools/virsh-domain.c +@@ -14344,7 +14344,7 @@ static const vshCmdOptDef opts_hotpatch[] = { + {.name = "action", + .type = VSH_OT_DATA, + .flags = VSH_OFLAG_REQ, +- .help = N_("hotpatch action, choose from , and ") ++ .help = N_("hotpatch action, choose from , , and ") + }, + {.name = "patch", + .type = VSH_OT_STRING, +@@ -14363,7 +14363,8 @@ VIR_ENUM_IMPL(virDomainHotpatchAction, + "none", + "apply", + "unapply", +- "query"); ++ "query", ++ "autoload"); + + static bool + cmdHotpatch(vshControl *ctl, +-- +2.30.0 + diff --git a/libvirt.spec b/libvirt.spec index f9adac148008aee4f1789c7c46e0de1255827fdd..40da7e1c6856effa8b7f4290cb1a92be0bab723e 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -101,7 +101,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 6.2.0 -Release: 30 +Release: 31 License: LGPLv2+ URL: https://libvirt.org/ @@ -196,6 +196,7 @@ Patch0083: docs-build-Don-t-include-stylesheet-in-intermediate-.patch Patch0084: tests-Replace-deprecated-ASN1-code.patch Patch0085: tests-disabale-storage-tests.patch Patch0086: Revert-tests-disabale-storage-tests.patch +Patch0087: hotpatch-virsh-support-autoload-mode.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -1930,6 +1931,9 @@ exit 0 %changelog +* Sat Feb 12 2022 imxcc +- hotpatch: virsh support autoload mode + * Fri Jun 29 2022 imxcc - Revert "tests: disabale storage tests"