libvirt/libvirt-add-get-tmm-memory-info-API-and-libvirtd-RPC.patch
Jiabo Feng 46011ccf7e libvirt update to version 6.2.0-65:
- remote: fix double free of migration params on error
- qemu: avoid deadlock in qemuDomainObjStopWorker We are dropping the only reference here so that the event loop thread is going to be exited synchronously. In order to avoid deadlocks we need to unlock the VM so that any handler being called can finish execution and thus even loop thread be finished too.
- virsh: add tmm main command word Add tmm command word into virsh tool to call get tmm memory info API. It makes virsh can use tmm main commmand to show tmm memory info on console. This command requires specific kernel and a kernel driver to make sure its regular function. If runnning environment missing the above reliance, this command will show error result on console.
- libvirt: add get tmm memory info API and libvirtd RPC Add the get tmm memory info API into libvirt-host. Also should add the RPC calls into libvirtd for API calling.
- libvirt: support the virtCCA feature Add cvm parameter into the type of LaunchSecurity which is a optional filed for libvirt xml. Its purpose is to pass the cvm parameter through to qemu. Also this patch support virsh edit to save cvm parameter into libvirt temporary xml.
- qemu_driver: Add calc_mode for dirtyrate statistics
- virsh: Add mode option to domdirtyrate-calc virsh api
- qemu: Generate command line for dirty-ring-size
- qemu: support dirty ring feature
- conf: Turn virDomainDef.kvm_features into a struct
- qemu_validate: Allow kvm hint-dedicated on non-passthrough VMs
- virDomainFeaturesKVMDefParse: Remove tautological "if"
- virDomainFeaturesKVMDefParse: Remove tautological "switch"
- virxml: Add virXMLPropUInt
- virxml: Add virXMLPropInt
- virxml: Add virXMLPropTristateSwitch
- virxml: Add virXMLPropTristateBool
- virDomainFeaturesKVMDefParse: Remove ctxt
- virDomainFeaturesDefParse: Factor out KVM parsing into separate function
- internal.h: Introduce and use VIR_IS_POW2()
- hotpatch: if hotpatch_path not in qemu.conf,the hotpatch doesn't antoload

Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
2024-06-13 11:02:43 +08:00

406 lines
13 KiB
Diff

From cd0f3755bd04bb58089d756400f20c75550e54f2 Mon Sep 17 00:00:00 2001
From: tujipei <tujipei@huawei.com>
Date: Wed, 12 Jun 2024 12:02:00 +0800
Subject: [PATCH] libvirt: add get tmm memory info API and libvirtd RPC Add the
get tmm memory info API into libvirt-host. Also should add the RPC calls into
libvirtd for API calling.
Signed-off-by: tujipei <tujipei@huawei.com>
---
include/libvirt/libvirt-host.h | 2 +
scripts/apibuild.py | 1 +
scripts/check-aclrules.py | 1 +
src/driver-hypervisor.h | 5 +
src/libvirt-host.c | 35 +++++++
src/libvirt_public.syms | 1 +
src/qemu/qemu_driver.c | 139 ++++++++++++++++++++++++++++
src/remote/remote_daemon_dispatch.c | 23 +++++
src/remote/remote_driver.c | 29 ++++++
src/remote/remote_protocol.x | 16 +++-
10 files changed, 251 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 6972834175..e7272ccb20 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -820,5 +820,7 @@ int virNodeAllocPages(virConnectPtr conn,
unsigned int cellCount,
unsigned int flags);
+char *virConnectGetTmmMemoryInfo(virConnectPtr conn,
+ unsigned int detail);
#endif /* LIBVIRT_HOST_H */
diff --git a/scripts/apibuild.py b/scripts/apibuild.py
index c98bcf6091..9b78754e5d 100755
--- a/scripts/apibuild.py
+++ b/scripts/apibuild.py
@@ -107,6 +107,7 @@ ignored_functions = {
"virDomainMigrateConfirm3Params": "private function for migration",
"virDomainMigratePrepareTunnel3Params": "private function for tunnelled migration",
"virErrorCopyNew": "private",
+ "virConnectGetTmmMemoryInfo": "private function for tmm",
}
ignored_macros = {
diff --git a/scripts/check-aclrules.py b/scripts/check-aclrules.py
index e196f81de9..aa5a589c85 100755
--- a/scripts/check-aclrules.py
+++ b/scripts/check-aclrules.py
@@ -54,6 +54,7 @@ whitelist = {
"localOnly": True,
"domainQemuAttach": True,
"domainHotpatchManage": True,
+ "connectGetTmmMemoryInfo": True,
}
# XXX this vzDomainMigrateConfirm3Params looks
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 82f808905d..e48b701365 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1402,6 +1402,10 @@ typedef int
typedef struct _virHypervisorDriver virHypervisorDriver;
typedef virHypervisorDriver *virHypervisorDriverPtr;
+typedef char *
+(*virDrvConnectGetTmmMemoryInfo)(virConnectPtr conn,
+ bool detail);
+
/**
* _virHypervisorDriver:
*
@@ -1664,4 +1668,5 @@ struct _virHypervisorDriver {
virDrvDomainBackupGetXMLDesc domainBackupGetXMLDesc;
virDrvDomainHotpatchManage domainHotpatchManage;
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
+ virDrvConnectGetTmmMemoryInfo connectGetTmmMemoryInfo;
};
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index bc3d1d2803..d0750d28cc 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1754,3 +1754,38 @@ virNodeGetSEVInfo(virConnectPtr conn,
virDispatchError(conn);
return -1;
}
+
+/*
+ * virConnectGetTmmMemoryInfo:
+ * @conn: pointer to the hypervisor connection
+ * @detail: whether libvirtd return detailed tmm memory information;
+ * the default value is 0 which means don't return detailed tmm memory information.
+ *
+ * If Tmm enable, then will fill the cotents of string buffer with tmm memory information.
+ *
+ * Returns string ptr in case of success, and NULL in case of failure.
+ */
+char *
+virConnectGetTmmMemoryInfo(virConnectPtr conn,
+ unsigned int detail)
+{
+ VIR_DEBUG("conn=%p", conn);
+
+ virResetLastError();
+
+ virCheckConnectReturn(conn, NULL);
+
+ if (conn->driver->connectGetTmmMemoryInfo) {
+ char *ret;
+ ret = conn->driver->connectGetTmmMemoryInfo(conn, detail);
+ if (!ret)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ error:
+ virDispatchError(conn);
+ return NULL;
+}
+
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index f006516208..284b7f7873 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -877,5 +877,6 @@ LIBVIRT_6.2.0 {
global:
virDomainHotpatchManage;
virDomainStartDirtyRateCalc;
+ virConnectGetTmmMemoryInfo;
} LIBVIRT_6.0.0;
# .... define new API here using predicted next version number ....
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 77a139c66b..1e3f63a39a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -23385,6 +23385,144 @@ qemuDomainStartDirtyRateCalc(virDomainPtr dom,
return ret;
}
+static int
+qemuConnectTmmInfoListAppend(char ***targetInfoStrList,
+ char **infoStrList,
+ int targetNumaNum,
+ int *startIndex,
+ int maxListSize)
+{
+ char *numStart;
+ int numaNode, index, ret = 0;
+
+ for (index = *startIndex; index < maxListSize; index++) {
+ if (strlen(infoStrList[index]) == 0)
+ break;
+
+ numStart = strstr(infoStrList[index], "node ");
+ if (!numStart)
+ return -1;
+
+ virSkipToDigit((const char **)(&numStart));
+ ret = virStrToLong_i(numStart, &numStart, 10, &numaNode);
+ if (ret < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get current numa node"));
+ return ret;
+ }
+
+ if (numaNode == targetNumaNum) {
+ ret = virStringListAdd(targetInfoStrList, infoStrList[index]);
+ if (ret < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s [%d]",
+ _("Failed to get add info list member"), index);
+ return ret;
+ }
+ } else {
+ break;
+ }
+ }
+
+ *startIndex = index;
+
+ return ret;
+}
+
+static char *
+qemuConnectTmmDetailInfoFormat(char *baseMeminfo,
+ char *slabInfo)
+{
+ int ret, i = 0, j = 0;
+ char *numStart, *numListStart, *format = NULL;
+ char **baseMeminfoSplits = virStringSplit(baseMeminfo, "\n", 0);
+ char **slabInfoSplits = virStringSplit(slabInfo, "\n", 0);
+ char **resultStrList = NULL;
+ int numaSize, numaIndex, headNumaNode;
+ ssize_t meminfoListSize = virStringListLength((const char * const *)baseMeminfoSplits);
+ ssize_t slabInfoSize = virStringListLength((const char * const *)slabInfoSplits);
+
+ numStart = strchr(baseMeminfoSplits[i], ':');
+ numListStart = strchr(baseMeminfoSplits[i], '(');
+ if (!numStart || !numListStart)
+ goto cleanup;
+
+ virSkipToDigit((const char **)(&numStart));
+ ret = virStrToLong_i(numStart, &numStart, 10, &numaSize);
+ if (ret < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get available numa size"));
+ goto cleanup;
+ }
+
+ ret = virStringListAdd(&resultStrList, baseMeminfoSplits[i++]);
+ if (ret < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s [%d]",
+ _("Failed to get add base memory info list member"), (i - 1));
+ goto cleanup;
+ }
+
+ virSkipToDigit((const char **)(&numListStart));
+ for (numaIndex = 0; *numListStart && numaIndex < numaSize; numaIndex++, numListStart++) {
+ ret = virStrToLong_i(numListStart, &numListStart, 10, &headNumaNode);
+ if (ret < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to get current numa node"));
+ goto cleanup;
+ }
+
+ ret = qemuConnectTmmInfoListAppend(&resultStrList, baseMeminfoSplits, headNumaNode, &i, meminfoListSize);
+ if (ret < 0)
+ goto cleanup;
+ ret = qemuConnectTmmInfoListAppend(&resultStrList, slabInfoSplits, headNumaNode, &j, slabInfoSize);
+ if (ret < 0)
+ goto cleanup;
+ }
+
+ format = virStringListJoin((const char **)resultStrList, "\n");
+
+ cleanup:
+ virStringListFree(baseMeminfoSplits);
+ virStringListFree(slabInfoSplits);
+ virStringListFree(resultStrList);
+ return format;
+}
+
+static char *
+qemuConnectGetTmmMemoryInfo(virConnectPtr conn G_GNUC_UNUSED,
+ bool detail)
+{
+ int maxLen = 10 * 1024;
+ char *meminfo = NULL;
+ g_autofree char *formatInfo = NULL;
+ g_autofree char *baseMeminfo = NULL;
+ g_autofree char *slabInfo = NULL;
+ g_autofree char *buddyInfo = NULL;
+
+ if (virFileReadAll("/sys/kernel/tmm/memory_info", maxLen, &baseMeminfo) < 0)
+ goto end;
+ if (detail && virFileReadAll("/sys/kernel/tmm/slab_info", maxLen, &slabInfo) < 0)
+ goto end;
+ if (detail && virFileReadAll("/sys/kernel/tmm/buddy_info", maxLen, &buddyInfo) < 0)
+ goto end;
+
+ if (detail) {
+ if (!virStringIsEmpty(baseMeminfo) && !virStringIsEmpty(slabInfo)) {
+ formatInfo = qemuConnectTmmDetailInfoFormat(baseMeminfo, slabInfo);
+ if (formatInfo == NULL)
+ goto end;
+ } else {
+ formatInfo = g_strdup_printf(_("%s%s"), baseMeminfo, slabInfo);
+ }
+
+ meminfo = g_strdup_printf(_("%s\n%s"), formatInfo, buddyInfo);
+ } else {
+ meminfo = g_steal_pointer(&baseMeminfo);
+ }
+
+end:
+ return meminfo;
+}
+
static virHypervisorDriver qemuHypervisorDriver = {
.name = QEMU_DRIVER_NAME,
@@ -23627,6 +23765,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainBackupGetXMLDesc = qemuDomainBackupGetXMLDesc, /* 6.0.0 */
.domainHotpatchManage = qemuDomainHotpatchManage, /* 6.2.0 */
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 6.2.0 */
+ .connectGetTmmMemoryInfo = qemuConnectGetTmmMemoryInfo, /* 6.2.0 */
};
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index 0bbcc05235..a9763cee7b 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -7268,6 +7268,29 @@ remoteDispatchNetworkPortGetParameters(virNetServerPtr server G_GNUC_UNUSED,
return rv;
}
+static int
+remoteDispatchConnectGetTmmMemoryInfo(virNetServerPtr server G_GNUC_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg G_GNUC_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_connect_get_tmm_memory_info_args *args,
+ remote_connect_get_tmm_memory_info_ret *ret)
+{
+ int rv = -1;
+ char *meminfo = NULL;
+ virConnectPtr conn = remoteGetHypervisorConn(client);
+
+ if (conn && (meminfo = virConnectGetTmmMemoryInfo(conn, args->detail))) {
+ rv = 0;
+ ret->meminfo = meminfo;
+ }
+
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+
+ return rv;
+}
+
/*----- Helpers. -----*/
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 9c272b4ff8..b597ae614c 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8253,6 +8253,34 @@ remoteDomainGetGuestInfo(virDomainPtr dom,
return rv;
}
+static char *
+remoteConnectGetTmmMemoryInfo(virConnectPtr conn,
+ bool detail)
+{
+ char *rv = NULL;
+ struct private_data *priv = conn->privateData;
+ remote_connect_get_tmm_memory_info_args args;
+ remote_connect_get_tmm_memory_info_ret ret;
+
+ remoteDriverLock(priv);
+
+ args.detail = detail;
+
+ memset(&ret, 0, sizeof(ret));
+
+ if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_TMM_MEMORY_INFO,
+ (xdrproc_t)xdr_remote_connect_get_tmm_memory_info_args, (char *)&args,
+ (xdrproc_t)xdr_remote_connect_get_tmm_memory_info_ret, (char *)&ret) < 0) {
+ goto done;
+ }
+
+ rv = ret.meminfo;
+
+ done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
/* get_nonnull_domain and get_nonnull_network turn an on-wire
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
* These can return NULL if underlying memory allocations fail,
@@ -8686,6 +8714,7 @@ static virHypervisorDriver hypervisor_driver = {
.domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */
.domainHotpatchManage = remoteDomainHotpatchManage, /* 6.2.0 */
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 6.2.0 */
+ .connectGetTmmMemoryInfo = remoteConnectGetTmmMemoryInfo /* 6.2.0 */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index d89cc1a087..f37bd332a1 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -3789,6 +3789,14 @@ struct remote_domain_start_dirty_rate_calc_args {
unsigned int flags;
};
+struct remote_connect_get_tmm_memory_info_args {
+ unsigned int detail;
+};
+
+struct remote_connect_get_tmm_memory_info_ret {
+ remote_nonnull_string meminfo;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -6698,5 +6706,11 @@ enum remote_procedure {
* @generate: both
* @acl: domain:read
*/
- REMOTE_PROC_DOMAIN_HOTPATCH_MANAGE = 800
+ REMOTE_PROC_DOMAIN_HOTPATCH_MANAGE = 800,
+
+ /**
+ * @generate: none
+ * @acl: connect:read
+ */
+ REMOTE_PROC_CONNECT_GET_TMM_MEMORY_INFO = 900
};
--
2.27.0