- Bugfix: Enhance the capability to trace the shutdown status of large VMS - conf: qemu: support provide inject secret for Hygon CSV - conf: qemu: add libvirt support reuse id for hygon CSV - Automatically unbind all devices' driver under same root port and bind to vfio-pci in the context of CVM. - Consistent coding style with opensource. - build: Make daemons depend on generated *_protocol.[ch] - Add the get tmm memory info API into libvirt-host. Also should add the RPC calls into libvirtd for API calling. - Add cvm parameter into the type of LaunchSecurity which is a optional filed for libvirt xml Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit d6a30a53977380d182cdf5f873c4ceb1ec29a85a)
510 lines
16 KiB
Diff
510 lines
16 KiB
Diff
From 96ec8dcd8c5ac0459259cf0d40a163bcee668484 Mon Sep 17 00:00:00 2001
|
|
From: ikarosYuuki <tujipei@huawei.com>
|
|
Date: Fri, 2 Aug 2024 14:18:11 +0800
|
|
Subject: [PATCH] Add the get tmm memory info API into libvirt-host. Also
|
|
should add the RPC calls into libvirtd for API calling.
|
|
|
|
---
|
|
include/libvirt/libvirt-host.h | 2 +
|
|
scripts/apibuild.py | 1 +
|
|
scripts/check-aclrules.py | 1 +
|
|
src/driver-hypervisor.h | 5 ++
|
|
src/libvirt-host.c | 36 ++++++++
|
|
src/libvirt_public.syms | 1 +
|
|
src/qemu/qemu_driver.c | 128 ++++++++++++++++++++++++++++
|
|
src/remote/remote_daemon_dispatch.c | 22 +++++
|
|
src/remote/remote_driver.c | 28 ++++++
|
|
src/remote/remote_protocol.x | 17 +++-
|
|
tools/virsh-host.c | 98 +++++++++++++++++++++
|
|
11 files changed, 338 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
|
|
index 3112f2b676..af7dede24e 100644
|
|
--- a/include/libvirt/libvirt-host.h
|
|
+++ b/include/libvirt/libvirt-host.h
|
|
@@ -1016,5 +1016,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 3ecc3eadf7..f1cfa5aa0a 100755
|
|
--- a/scripts/apibuild.py
|
|
+++ b/scripts/apibuild.py
|
|
@@ -109,6 +109,7 @@ ignored_functions = {
|
|
"virDomainMigrateConfirm3Params": "private function for migration",
|
|
"virDomainMigratePrepareTunnel3Params": "private function for tunnelled migration",
|
|
"virErrorCopyNew": "private",
|
|
+ "virConnectGetTmmMemoryInfo": "private function for tmm",
|
|
}
|
|
|
|
# The version in the .sym file might different from
|
|
diff --git a/scripts/check-aclrules.py b/scripts/check-aclrules.py
|
|
index e39dbd2ba8..e6bcf00b11 100755
|
|
--- a/scripts/check-aclrules.py
|
|
+++ b/scripts/check-aclrules.py
|
|
@@ -54,6 +54,7 @@ permitted = {
|
|
"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 e54af0515f..619a091ffa 100644
|
|
--- a/src/driver-hypervisor.h
|
|
+++ b/src/driver-hypervisor.h
|
|
@@ -1457,6 +1457,10 @@ typedef char *
|
|
|
|
typedef struct _virHypervisorDriver virHypervisorDriver;
|
|
|
|
+typedef char *
|
|
+(*virDrvConnectGetTmmMemoryInfo)(virConnectPtr conn,
|
|
+ bool detail);
|
|
+
|
|
/**
|
|
* _virHypervisorDriver:
|
|
*
|
|
@@ -1728,4 +1732,5 @@ struct _virHypervisorDriver {
|
|
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
|
|
virDrvDomainFDAssociate domainFDAssociate;
|
|
virDrvDomainHotpatchManage domainHotpatchManage;
|
|
+ virDrvConnectGetTmmMemoryInfo connectGetTmmMemoryInfo;
|
|
};
|
|
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
|
|
index e67b36812e..e763d5c86c 100644
|
|
--- a/src/libvirt-host.c
|
|
+++ b/src/libvirt-host.c
|
|
@@ -1829,3 +1829,39 @@ 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.
|
|
+ *
|
|
+ * Since: 9.7.0
|
|
+ */
|
|
+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 8b38fe9a5f..72efec0b61 100644
|
|
--- a/src/libvirt_public.syms
|
|
+++ b/src/libvirt_public.syms
|
|
@@ -941,6 +941,7 @@ LIBVIRT_9.7.0 {
|
|
global:
|
|
virNetworkGetMetadata;
|
|
virNetworkSetMetadata;
|
|
+ virConnectGetTmmMemoryInfo;
|
|
} LIBVIRT_9.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 d7fb93b3b3..5a5aa28449 100644
|
|
--- a/src/qemu/qemu_driver.c
|
|
+++ b/src/qemu/qemu_driver.c
|
|
@@ -20010,6 +20010,133 @@ qemuDomainHotpatchManage(virDomainPtr domain,
|
|
return ret;
|
|
}
|
|
|
|
+static int
|
|
+qemuConnectTmmInfoListAppend(char **format,
|
|
+ char **infoStrList,
|
|
+ int targetNumaNum,
|
|
+ int *startIndex,
|
|
+ int maxListSize)
|
|
+{
|
|
+ char *numStart;
|
|
+ char *strPtr = NULL;
|
|
+ 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) {
|
|
+ strPtr = *format;
|
|
+ *format = g_strconcat(*format, "\n", infoStrList[index], NULL);
|
|
+ free(strPtr);
|
|
+ } 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 = g_strsplit(baseMeminfo, "\n", 0);
|
|
+ char **slabInfoSplits = g_strsplit(slabInfo, "\n", 0);
|
|
+ int numaSize, numaIndex, headNumaNode;
|
|
+ ssize_t meminfoListSize = g_strv_length(baseMeminfoSplits);
|
|
+ ssize_t slabInfoSize = g_strv_length(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;
|
|
+ }
|
|
+
|
|
+ format = g_strconcat(baseMeminfoSplits[i++], NULL);
|
|
+
|
|
+ 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(&format, baseMeminfoSplits, headNumaNode, &i, meminfoListSize);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+ ret = qemuConnectTmmInfoListAppend(&format, slabInfoSplits, headNumaNode, &j, slabInfoSize);
|
|
+ if (ret < 0)
|
|
+ goto cleanup;
|
|
+ }
|
|
+
|
|
+cleanup:
|
|
+ g_strfreev(baseMeminfoSplits);
|
|
+ g_strfreev(slabInfoSplits);
|
|
+ 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,
|
|
.connectURIProbe = qemuConnectURIProbe,
|
|
@@ -20260,6 +20387,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
|
|
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
|
|
.domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
|
|
.domainFDAssociate = qemuDomainFDAssociate, /* 9.0.0 */
|
|
+ .connectGetTmmMemoryInfo = qemuConnectGetTmmMemoryInfo, /* 9.0.0 */
|
|
};
|
|
|
|
|
|
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
|
|
index 7542caa952..10f343843a 100644
|
|
--- a/src/remote/remote_daemon_dispatch.c
|
|
+++ b/src/remote/remote_daemon_dispatch.c
|
|
@@ -7125,6 +7125,28 @@ remoteDispatchNetworkPortGetParameters(virNetServer *server G_GNUC_UNUSED,
|
|
return rv;
|
|
}
|
|
|
|
+static int
|
|
+remoteDispatchConnectGetTmmMemoryInfo(virNetServer *server G_GNUC_UNUSED,
|
|
+ virNetServerClient *client,
|
|
+ virNetMessage *msg G_GNUC_UNUSED,
|
|
+ struct virNetMessageError *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 9350e811d6..4b9ad30ed6 100644
|
|
--- a/src/remote/remote_driver.c
|
|
+++ b/src/remote/remote_driver.c
|
|
@@ -7406,6 +7406,33 @@ remoteDomainFDAssociate(virDomainPtr domain,
|
|
return 0;
|
|
}
|
|
|
|
+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.
|
|
@@ -7849,6 +7876,7 @@ static virHypervisorDriver hypervisor_driver = {
|
|
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
|
|
.domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */
|
|
.domainFDAssociate = remoteDomainFDAssociate, /* 9.0.0 */
|
|
+ .connectGetTmmMemoryInfo = remoteConnectGetTmmMemoryInfo /* 9.0.0 */
|
|
};
|
|
|
|
static virNetworkDriver network_driver = {
|
|
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
|
|
index eea11df2ea..39069ce207 100644
|
|
--- a/src/remote/remote_protocol.x
|
|
+++ b/src/remote/remote_protocol.x
|
|
@@ -3973,6 +3973,15 @@ struct remote_domain_fd_associate_args {
|
|
remote_nonnull_string name;
|
|
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. */
|
|
@@ -7038,5 +7047,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
|
|
};
|
|
diff --git a/tools/virsh-host.c b/tools/virsh-host.c
|
|
index 6c14be865f..7fdd6aed53 100644
|
|
--- a/tools/virsh-host.c
|
|
+++ b/tools/virsh-host.c
|
|
@@ -1826,6 +1826,98 @@ cmdHypervisorCPUBaseline(vshControl *ctl,
|
|
return ret;
|
|
}
|
|
|
|
+/*
|
|
+ * "securememinfo" command
|
|
+ */
|
|
+static const vshCmdInfo info_tmm[] = {
|
|
+ {.name = "help",
|
|
+ .data = N_("Interaction with the tmm")
|
|
+ },
|
|
+ {.name = "desc",
|
|
+ .data = N_("Call the host kernel dev which is provided for virsh to use receiving tmm informations.")
|
|
+ },
|
|
+ {.name = NULL}
|
|
+};
|
|
+
|
|
+static const vshCmdOptDef opts_tmm[] = {
|
|
+ {.name = "dev",
|
|
+ .type = VSH_OT_DATA,
|
|
+ .flags = VSH_OFLAG_REQ,
|
|
+ .help = N_("Device name of host kernel dev")
|
|
+ },
|
|
+ {.name = "detail",
|
|
+ .type = VSH_OT_BOOL,
|
|
+ .help = N_("print detailed info if this option contained in cmd")
|
|
+ },
|
|
+ {.name = NULL}
|
|
+};
|
|
+
|
|
+static bool
|
|
+virshGetTmmMemoryInfo(vshControl *ctl,
|
|
+ const vshCmd *cmd)
|
|
+{
|
|
+ char *tmmMemoryInfo = NULL;
|
|
+ bool detail;
|
|
+ virshControl *priv = ctl->privData;
|
|
+
|
|
+ detail = vshCommandOptBool(cmd, "detail");
|
|
+ if (!(tmmMemoryInfo = virConnectGetTmmMemoryInfo(priv->conn, (unsigned int)detail))) {
|
|
+ vshError(ctl, _("Get tmm_memory_info failed"));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ vshPrintExtra(ctl, _("%s"), tmmMemoryInfo);
|
|
+
|
|
+ VIR_FREE(tmmMemoryInfo);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+typedef bool
|
|
+(*virshTmmFunc)(vshControl *ctl,
|
|
+ const vshCmd *cmd);
|
|
+
|
|
+struct _virshTmmFuncInfo {
|
|
+ const char *devName;
|
|
+ virshTmmFunc funcPtr;
|
|
+};
|
|
+
|
|
+typedef struct _virshTmmFuncInfo virshTmmFuncInfo;
|
|
+
|
|
+static virshTmmFuncInfo virshTmmFuncMap[] = {
|
|
+ {"tmm_memory_info", virshGetTmmMemoryInfo},
|
|
+};
|
|
+
|
|
+static bool
|
|
+virshTmmRunFunc(vshControl *ctl,
|
|
+ const char *devName,
|
|
+ const vshCmd *cmd)
|
|
+{
|
|
+ int funcIndex;
|
|
+
|
|
+ for (funcIndex = 0; funcIndex < sizeof(virshTmmFuncMap) / sizeof(virshTmmFuncInfo); funcIndex++) {
|
|
+ if (strcmp(devName, virshTmmFuncMap[funcIndex].devName) == 0) {
|
|
+ virshTmmFuncMap[funcIndex].funcPtr(ctl, cmd);
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ vshError(ctl, _("Invalid dev name"));
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static bool
|
|
+cmdTmm(vshControl *ctl, const vshCmd *cmd)
|
|
+{
|
|
+ const char *devName = NULL;
|
|
+
|
|
+ if (vshCommandOptStringReq(ctl, cmd, "dev", &devName) < 0)
|
|
+ return false;
|
|
+
|
|
+ if (!virshTmmRunFunc(ctl, devName, cmd))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
|
|
const vshCmdDef hostAndHypervisorCmds[] = {
|
|
{.name = "allocpages",
|
|
@@ -1960,5 +2052,11 @@ const vshCmdDef hostAndHypervisorCmds[] = {
|
|
.info = info_version,
|
|
.flags = 0
|
|
},
|
|
+ {.name = "tmm",
|
|
+ .handler = cmdTmm,
|
|
+ .opts = opts_tmm,
|
|
+ .info = info_tmm,
|
|
+ .flags = 0
|
|
+ },
|
|
{.name = NULL}
|
|
};
|
|
--
|
|
2.41.0.windows.1
|
|
|