[libvirt PATCH v3] hypervisor: Move interface mgmt methods to hypervisor

2023-10-19 Thread Praveen K Paladugu
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.

Signed-off-by: Praveen K Paladugu 
---
 po/POTFILES   |   1 +
 src/hypervisor/domain_interface.c | 368 ++
 src/hypervisor/domain_interface.h |  41 
 src/hypervisor/meson.build|   1 +
 src/libvirt_private.syms  |   8 +
 src/qemu/qemu_command.c   |   6 +-
 src/qemu/qemu_hotplug.c   |   5 +-
 src/qemu/qemu_interface.c | 339 +--
 src/qemu/qemu_interface.h |  11 -
 src/qemu/qemu_process.c   |   5 +-
 10 files changed, 434 insertions(+), 351 deletions(-)
 create mode 100644 src/hypervisor/domain_interface.c
 create mode 100644 src/hypervisor/domain_interface.h

diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
 src/hyperv/hyperv_wmi.c
 src/hypervisor/domain_cgroup.c
 src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
 src/hypervisor/virhostdev.c
 src/interface/interface_backend_netcf.c
 src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c 
b/src/hypervisor/domain_interface.c
new file mode 100644
index 00..f726cb2bea
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "virconftypes.h"
+#include "virmacaddr.h"
+#include "virnetdevtap.h"
+#include "domain_audit.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "viralloc.h"
+#include "virebtables.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virnetdevbridge.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_LOG_INIT("interface.interface_connect");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+return (virDomainNetIsVirtioModel(net) ||
+net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @driver: qemu driver data
+ * @net: pointer to the VM's interface description
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+virDomainNetDef *net,
+ebtablesContext *ebtables,
+bool macFilter,
+bool privileged,
+int *tapfd,
+size_t tapfdSize)
+{
+virMacAddr tapmac;
+int ret = -1;
+unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+bool template_ifname = false;
+const char *tunpath = "/dev/net/tun";
+const char *auditdev = tunpath;
+
+if (net->backend.tap) {
+tunpath = net->backend.tap;
+if (!privileged) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("cannot use custom tap device in session mode"));
+goto cleanup;
+}
+}
+
+if (virDomainInterfaceIsVnetCompatModel(net))
+tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+if (!net->ifname) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("target dev must be supplied when managed='no'"));
+goto cleanup;
+}
+if (virNetDevExists(net->ifname) != 1) {
+vir

[libvirt PATCH v2] hypervisor: Move interface mgmt methods to hypervisor

2023-10-16 Thread Praveen K Paladugu
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.

Signed-off-by: Praveen K Paladugu 
---
 po/POTFILES   |   1 +
 src/hypervisor/domain_interface.c | 280 ++
 src/hypervisor/domain_interface.h |  39 +
 src/hypervisor/meson.build|   1 +
 src/libvirt_private.syms  |   6 +
 src/qemu/qemu_command.c   |   7 +-
 src/qemu/qemu_hotplug.c   |   3 +-
 src/qemu/qemu_interface.c | 246 +-
 src/qemu/qemu_interface.h |   6 -
 src/qemu/qemu_process.c   |   3 +-
 10 files changed, 343 insertions(+), 249 deletions(-)
 create mode 100644 src/hypervisor/domain_interface.c
 create mode 100644 src/hypervisor/domain_interface.h

diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
 src/hyperv/hyperv_wmi.c
 src/hypervisor/domain_cgroup.c
 src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
 src/hypervisor/virhostdev.c
 src/interface/interface_backend_netcf.c
 src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c 
b/src/hypervisor/domain_interface.c
new file mode 100644
index 00..592c4253df
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "virconftypes.h"
+#include "virmacaddr.h"
+#include "virnetdevtap.h"
+#include "domain_audit.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "viralloc.h"
+#include "virebtables.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virnetdevbridge.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_LOG_INIT("interface.interface_connect");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+return (virDomainNetIsVirtioModel(net) ||
+net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @driver: qemu driver data
+ * @net: pointer to the VM's interface description
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+virDomainNetDef *net,
+ebtablesContext *ebtables,
+bool macFilter,
+bool privileged,
+int *tapfd,
+size_t tapfdSize)
+{
+virMacAddr tapmac;
+int ret = -1;
+unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+bool template_ifname = false;
+const char *tunpath = "/dev/net/tun";
+const char *auditdev = tunpath;
+
+if (net->backend.tap) {
+tunpath = net->backend.tap;
+if (!privileged) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("cannot use custom tap device in session mode"));
+goto cleanup;
+}
+}
+VIR_WARN("PPK: interfaceEthernetConnect Called\n");
+if (virDomainInterfaceIsVnetCompatModel(net))
+tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+if (!net->ifname) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("target dev must be supplied when managed='no'"));
+goto

[libvirt PATCH] hypervisor: Move interface mgmt methods to hypervisor

2023-10-12 Thread Praveen K Paladugu
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.

Signed-off-by: Praveen K Paladugu 
---
 po/POTFILES   |   1 +
 src/hypervisor/domain_interface.c | 279 ++
 src/hypervisor/domain_interface.h |  38 
 src/hypervisor/meson.build|   1 +
 src/libvirt_private.syms  |   6 +
 src/qemu/qemu_command.c   |   7 +-
 src/qemu/qemu_hotplug.c   |   3 +-
 src/qemu/qemu_interface.c | 246 +-
 src/qemu/qemu_interface.h |   6 -
 src/qemu/qemu_process.c   |   3 +-
 10 files changed, 341 insertions(+), 249 deletions(-)
 create mode 100644 src/hypervisor/domain_interface.c
 create mode 100644 src/hypervisor/domain_interface.h

diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
 src/hyperv/hyperv_wmi.c
 src/hypervisor/domain_cgroup.c
 src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
 src/hypervisor/virhostdev.c
 src/interface/interface_backend_netcf.c
 src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c 
b/src/hypervisor/domain_interface.c
new file mode 100644
index 00..b01b6ee767
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright Microsoft Corp. 2023
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "virmacaddr.h"
+#include "virnetdevtap.h"
+#include "virconftypes.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "domain_audit.h"
+#include "virebtables.h"
+#include "virlog.h"
+#include "virfile.h"
+#include "viralloc.h"
+#include "virnetdevbridge.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_LOG_INIT("interface.interface_connect");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+return (virDomainNetIsVirtioModel(net) ||
+net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @driver: qemu driver data
+ * @net: pointer to the VM's interface description
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+virDomainNetDef *net,
+ebtablesContext *ebtables,
+bool macFilter,
+bool privileged,
+int *tapfd,
+size_t tapfdSize)
+{
+virMacAddr tapmac;
+int ret = -1;
+unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+bool template_ifname = false;
+const char *tunpath = "/dev/net/tun";
+const char *auditdev = tunpath;
+
+if (net->backend.tap) {
+tunpath = net->backend.tap;
+if (!privileged) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("cannot use custom tap device in session mode"));
+goto cleanup;
+}
+}
+VIR_WARN("PPK: interfaceEthernetConnect Called\n");
+if (virDomainInterfaceIsVnetCompatModel(net))
+tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+if (!net->ifname) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("target dev must be supplied when managed='no'"));
+goto cleanup;
+}
+if (virNet

[libvirt PATCH 2/2] ch: support serial and console devices in parallel

2023-10-10 Thread Praveen K Paladugu
Starting v18, cloud-hypervisor supports serial and console devices in
parallel. Drop related check based on ch version.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 28 ++--
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 866f0d899a..c0d6c75b1d 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -142,10 +142,11 @@ virDomainXMLPrivateDataCallbacks 
virCHDriverPrivateDataCallbacks = {
 
 static int
 chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
-  const virDomainDef *def G_GNUC_UNUSED,
-  void *opaque G_GNUC_UNUSED,
+  const virDomainDef *def,
+  void *opaque,
   void *parseOpaque G_GNUC_UNUSED)
 {
+virCHDriver *driver = opaque;
 switch (dev->type) {
 case VIR_DOMAIN_DEVICE_DISK:
 case VIR_DOMAIN_DEVICE_NET:
@@ -191,18 +192,25 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
 return -1;
 }
 
-if ((def->nconsoles &&
- def->consoles[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)
-&& (def->nserials &&
-def->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+if (!virBitmapIsBitSet(driver->chCaps, CH_SERIAL_CONSOLE_IN_PARALLEL)) {
+if ((def->nconsoles &&
+def->consoles[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)
+&& (def->nserials &&
+def->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only a single console or serial can be configured 
for this domain"));
-return -1;
-} else if (def->nconsoles > 1) {
+return -1;
+}
+}
+
+
+if (def->nconsoles > 1) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only a single console can be configured for this 
domain"));
 return -1;
-} else if (def->nserials > 1) {
+}
+
+if (def->nserials > 1) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only a single serial can be configured for this 
domain"));
 return -1;
-- 
2.41.0



[libvirt PATCH 1/2] ch: use payload api to send kernel details

2023-10-10 Thread Praveen K Paladugu
Starting with v28.0 cloud-hypervisor requires the use of "payload" api to pass
kernel, initramfs and cmdline options. Extend ch driver to use the new
api based on ch version.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_capabilities.c | 55 
 src/ch/ch_capabilities.h | 34 +
 src/ch/ch_conf.h |  6 +
 src/ch/ch_driver.c   |  3 +++
 src/ch/ch_monitor.c  | 48 +++
 src/ch/ch_monitor.h  |  4 ++-
 src/ch/ch_process.c  |  2 +-
 src/ch/meson.build   |  2 ++
 8 files changed, 147 insertions(+), 7 deletions(-)
 create mode 100644 src/ch/ch_capabilities.c
 create mode 100644 src/ch/ch_capabilities.h

diff --git a/src/ch/ch_capabilities.c b/src/ch/ch_capabilities.c
new file mode 100644
index 00..b10485820c
--- /dev/null
+++ b/src/ch/ch_capabilities.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright Microsoft Corp. 2023
+ *
+ * ch_capabilities.h: CH capabilities
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include "ch_capabilities.h"
+
+static void
+virCHCapsSet(virBitmap *chCaps,
+   virCHCapsFlags flag)
+{
+ignore_value(virBitmapSetBit(chCaps, flag));
+}
+
+/**
+ * virCHCapsInitCHVersionCaps:
+ *
+ * Set all CH capabilities based on version of CH.
+ */
+virBitmap *
+virCHCapsInitCHVersionCaps(int version)
+{
+g_autoptr(virBitmap) chCaps = NULL;
+chCaps = virBitmapNew(CH_CAPS_LAST);
+
+/* Version 28 deprecated kernel API:
+ * https://github.com/cloud-hypervisor/cloud-hypervisor/releases/tag/v28.0
+ */
+if (version >= 2800)
+virCHCapsSet(chCaps, CH_KERNEL_API_DEPRCATED);
+
+
+/* Starting Version 18, serial and console can be used in parallel */
+if (version >= 1800)
+virCHCapsSet(chCaps, CH_SERIAL_CONSOLE_IN_PARALLEL);
+
+return g_steal_pointer(&chCaps);
+
+}
diff --git a/src/ch/ch_capabilities.h b/src/ch/ch_capabilities.h
new file mode 100644
index 00..703a6dbfe2
--- /dev/null
+++ b/src/ch/ch_capabilities.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright Microsoft Corp. 2023
+ *
+ * ch_capabilities.h: CH capabilities
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include "virbitmap.h"
+
+
+typedef enum {
+/* 0 */
+CH_KERNEL_API_DEPRCATED, /* Use `payload` in place of `kernel` api */
+CH_SERIAL_CONSOLE_IN_PARALLEL, /* Serial and Console ports can work in 
parallel */
+
+CH_CAPS_LAST /* this must always be the last item */
+} virCHCapsFlags;
+
+virBitmap *
+virCHCapsInitCHVersionCaps(int version);
diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index b927621a97..5b9b42540d 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -22,6 +22,7 @@
 
 #include "virdomainobjlist.h"
 #include "virthread.h"
+#include "ch_capabilities.h"
 
 #define CH_DRIVER_NAME "CH"
 #define CH_CMD "cloud-hypervisor"
@@ -54,6 +55,11 @@ struct _virCHDriver
  * lockless access thereafter */
 virCaps *caps;
 
+/* Immutable pointer, Immutable object
+ * Initialized once and reused as needed
+ */
+virBitmap *chCaps;
+
 /* Immutable pointer, Immutable object */
 virDomainXMLOption *xmlopt;
 
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index b62645a8c8..bd271fc0ee 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "ch_capabilities.h"
 #include "ch_conf.h"
 #include "ch_domain.h"
 #include "ch_driver.h"
@@ -899,6 +900,8 @@ static int chStateInitialize(bool privileged,
 goto 

[libvirt PATCH 0/2] ch: Use payload api

2023-10-10 Thread Praveen K Paladugu
Introduced virCHCapsInitCHVersionCaps to check and cache capabilities of
cloud-hypervisor based on its version. Modified ch driver to use "payload" api
to pass kernel, initramfs and cmdline options to cloud-hypervisor.

Cloud-hypervisor currently has a single LTS release, v28, that will be supported
until May 24. All versions older than v28 have reached EOL. Can I bump up the
min version of cloud-hypervisor to v28 in ch driver? If I can bump up the min
supported version in ch driver, I can drop a check in this commit related to
supporting serial and console devices in parallel.

Praveen K Paladugu (2):
  ch: use payload api to send kernel details
  ch: support serial and console devices in parallel

 src/ch/ch_capabilities.c | 55 
 src/ch/ch_capabilities.h | 34 +
 src/ch/ch_conf.h |  6 +
 src/ch/ch_domain.c   | 28 
 src/ch/ch_driver.c   |  3 +++
 src/ch/ch_monitor.c  | 48 +++
 src/ch/ch_monitor.h  |  4 ++-
 src/ch/ch_process.c  |  2 +-
 src/ch/meson.build   |  2 ++
 9 files changed, 165 insertions(+), 17 deletions(-)
 create mode 100644 src/ch/ch_capabilities.c
 create mode 100644 src/ch/ch_capabilities.h

-- 
2.41.0



[libvirt PATCH v4] ch: Fix cloud-hypervisor version processing

2023-09-08 Thread Praveen K Paladugu
Refactor the version processing logic in ch driver to support versions
from non-release cloud-hypervisor binaries. This version also supports
versions with branch prefixes in them.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index a8565d9537..f421af5121 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -172,6 +172,29 @@ virCHDriverConfigDispose(void *obj)
 
 #define MIN_VERSION ((15 * 100) + (0 * 1000) + (0))
 
+/**
+ * chPreProcessVersionString:
+ *
+ * Returns: a pointer to numerical version without branch/commit info
+ */
+static char *
+chPreProcessVersionString(char *version)
+{
+char *tmp = strrchr(version, '/');
+
+if (tmp)
+version = tmp + 1;
+
+if (version[0] == 'v')
+version++;
+
+tmp = strchr(version, '-');
+if (tmp)
+*tmp = '\0';
+
+return version;
+}
+
 int
 chExtractVersion(virCHDriver *driver)
 {
@@ -193,13 +216,20 @@ chExtractVersion(virCHDriver *driver)
 
 tmp = help;
 
-/* expected format: cloud-hypervisor v.. */
-if ((tmp = STRSKIP(tmp, "cloud-hypervisor v")) == NULL) {
+/* Below are example version formats and expected outputs:
+ *  cloud-hypervisor v32.0.0 (expected: 32.0.0)
+ *  cloud-hypervisor v33.0-104-ge0e3779e-dirty (expected: 33.0)
+ *  cloud-hypervisor testing/v32.0.131-1-ga5d6db5c-dirty (expected: 
32.0.131)
+ */
+if ((tmp = STRSKIP(tmp, "cloud-hypervisor ")) == NULL) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected output of cloud-hypervisor binary"));
 return -1;
 }
 
+tmp = chPreProcessVersionString(tmp);
+VIR_DEBUG("Cloud-Hypervisor version detected: %s", tmp);
+
 if (virStringParseVersion(&version, tmp, true) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to parse cloud-hypervisor version: %1$s"), 
tmp);
-- 
2.41.0



[libvirt PATCH v3] ch: Fix cloud-hypervisor version processing

2023-09-06 Thread Praveen K Paladugu
Refactor the version processing logic in ch driver to support versions
from non-release cloud-hypervisor binaries. This version also supports
versions with branch prefixes in them.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c | 42 --
 1 file changed, 40 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index a8565d9537..5573119b23 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -172,6 +172,37 @@ virCHDriverConfigDispose(void *obj)
 
 #define MIN_VERSION ((15 * 100) + (0 * 1000) + (0))
 
+/**
+ * chPreProcessVersionString:
+ *
+ * Returns: a pointer to numerical version without branch/commit info
+ */
+static char *
+chPreProcessVersionString(char *version)
+{
+char *tmp_version = version;
+g_autofree char *ret_version = NULL;
+char *sub_string;
+
+if ((sub_string = strrchr(version, '/')) != NULL) {
+tmp_version = sub_string + 1;
+}
+
+if (tmp_version[0] == 'v') {
+tmp_version = tmp_version + 1;
+}
+
+// Duplicate the string in both cases. This would allow the calling method
+// free the returned string in a consistent manner.
+if ((sub_string = strchr(tmp_version, '-')) != NULL) {
+ret_version = g_strndup(tmp_version, sub_string - tmp_version);
+} else{
+ret_version = g_strdup(tmp_version);
+}
+
+return g_steal_pointer(&ret_version);
+
+}
 int
 chExtractVersion(virCHDriver *driver)
 {
@@ -193,13 +224,20 @@ chExtractVersion(virCHDriver *driver)
 
 tmp = help;
 
-/* expected format: cloud-hypervisor v.. */
-if ((tmp = STRSKIP(tmp, "cloud-hypervisor v")) == NULL) {
+/* Below are some example version formats and expected outputs:
+ *  cloud-hypervisor v32.0.0 (expected: 32.0.0)
+ *  cloud-hypervisor v33.0-104-ge0e3779e-dirty (expected: 33.0)
+ *  cloud-hypervisor testing/v32.0.131-1-ga5d6db5c-dirty (expected: 
32.0.131)
+ */
+if ((tmp = STRSKIP(tmp, "cloud-hypervisor ")) == NULL) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected output of cloud-hypervisor binary"));
 return -1;
 }
 
+tmp = chPreProcessVersionString(tmp);
+VIR_DEBUG("Cloud-Hypervisor version detected: %s", tmp);
+
 if (virStringParseVersion(&version, tmp, true) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to parse cloud-hypervisor version: %1$s"), 
tmp);
-- 
2.41.0



[libvirt PATCH v2] ch: Fix cloud-hypervisor version processing

2023-09-05 Thread Praveen K Paladugu
Refactor the version processing logic in ch driver to support versions
from non-release cloud-hypervisor binaries. This version also supports
versions with branch prefixes in them.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c | 39 ---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index a8565d9537..a0849bfbd6 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -172,6 +172,33 @@ virCHDriverConfigDispose(void *obj)
 
 #define MIN_VERSION ((15 * 100) + (0 * 1000) + (0))
 
+/**
+ * chPreProcessVersionString - crop branch, commit info and return just the 
version
+ */
+static char *
+chPreProcessVersionString(char *version)
+{
+g_autofree char *new_version = version;
+char *tmp_version;
+
+if ((tmp_version = strrchr(version, '/')) != NULL) {
+new_version = tmp_version + 1;
+}
+
+if (new_version[0] == 'v') {
+new_version = new_version + 1;
+}
+// Duplicate the string in both cases. This would allow the calling method
+// free the returned string in a consistent manner.
+if ((tmp_version = strchr(new_version, '-')) != NULL) {
+new_version = g_strndup(new_version, tmp_version - new_version);
+} else{
+new_version = g_strdup(new_version);
+}
+
+return g_steal_pointer(&new_version);
+
+}
 int
 chExtractVersion(virCHDriver *driver)
 {
@@ -193,19 +220,25 @@ chExtractVersion(virCHDriver *driver)
 
 tmp = help;
 
-/* expected format: cloud-hypervisor v.. */
-if ((tmp = STRSKIP(tmp, "cloud-hypervisor v")) == NULL) {
+/* Below are some example version formats and expected outputs:
+ *  cloud-hypervisor v32.0.0 (expected: 32.0.0)
+ *  cloud-hypervisor v33.0-104-ge0e3779e-dirty (expected: 33.0)
+ *  cloud-hypervisor testing/v32.0.131-1-ga5d6db5c-dirty (expected: 
32.0.131)
+ */
+if ((tmp = STRSKIP(tmp, "cloud-hypervisor ")) == NULL) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpected output of cloud-hypervisor binary"));
 return -1;
 }
 
+tmp = chPreProcessVersionString(tmp);
+VIR_DEBUG("Cloud-Hypervisor version detected: %s", tmp);
+
 if (virStringParseVersion(&version, tmp, true) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to parse cloud-hypervisor version: %1$s"), 
tmp);
 return -1;
 }
-
 if (version < MIN_VERSION) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cloud-Hypervisor version is too old (v15.0 is the 
minimum supported version)"));
-- 
2.41.0



[libvirt PATCH 1/1] ch: Do not add stub console to ch VMs

2023-02-09 Thread Praveen K Paladugu
virDomainDefAddConsoleCompat in post parsing step appends a stub console
of type VIR_DOMAIN_CHR_TYPE_NULL to ch VMs' Domain XML. Cloud-hypervisor's
deviceValidateCallback (chValidateDomainDeviceDef) checks that the type of
stub console is not of type VIR_DOMAIN_CHR_TYPE_PTY and throws an error.

This commit introduces NO_STUB_CONSOLE feature check to Domain features and
uses it to skip adding stub console to ch VMs.

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 1 +
 src/conf/domain_conf.c | 7 ---
 src/conf/domain_conf.h | 1 +
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 83defbb416..cf98654479 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -262,6 +262,7 @@ virDomainDefParserConfig virCHDriverDomainDefParserConfig = 
{
 .domainPostParseBasicCallback = virCHDomainDefPostParseBasic,
 .domainPostParseCallback = virCHDomainDefPostParse,
 .deviceValidateCallback = chValidateDomainDeviceDef,
+.features = VIR_DOMAIN_DEF_FEATURE_NO_STUB_CONSOLE,
 };
 
 virCHMonitor *
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ff1c78ecd1..a5578324b9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -21751,9 +21751,10 @@ virDomainDefAddImplicitVideo(virDomainDef *def, 
virDomainXMLOption *xmlopt)
 int
 virDomainDefAddImplicitDevices(virDomainDef *def, virDomainXMLOption *xmlopt)
 {
-if (virDomainDefAddConsoleCompat(def) < 0)
-return -1;
-
+if ((xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_NO_STUB_CONSOLE) == 
0) {
+if (virDomainDefAddConsoleCompat(def) < 0)
+return -1;
+}
 if (virDomainDefAddImplicitControllers(def) < 0)
 return -1;
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e684edcf95..62f80d653d 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3231,6 +3231,7 @@ typedef enum {
 VIR_DOMAIN_DEF_FEATURE_FW_AUTOSELECT = (1 << 7),
 VIR_DOMAIN_DEF_FEATURE_NET_MODEL_STRING = (1 << 8),
 VIR_DOMAIN_DEF_FEATURE_DISK_FD = (1 << 9),
+VIR_DOMAIN_DEF_FEATURE_NO_STUB_CONSOLE = (1 << 10),
 } virDomainDefFeatures;
 
 
-- 
2.34.1



[libvirt PATCH 0/1] Do not add stub console to ch VMs

2023-02-09 Thread Praveen K Paladugu
This patch resolves https://gitlab.com/libvirt/libvirt/-/issues/344

I tested various versions of cloud-hypervisor between v15 - v29.
All of them fail to start a test VM without this patch.

Praveen K Paladugu (1):
  ch: Do not add stub console to ch VMs

 src/ch/ch_domain.c | 1 +
 src/conf/domain_conf.c | 7 ---
 src/conf/domain_conf.h | 1 +
 3 files changed, 6 insertions(+), 3 deletions(-)

-- 
2.34.1



Re: Live migration support for Cloud-Hypervisor VMs

2022-08-03 Thread Praveen K Paladugu



Thanks for the details and recommendations Daniel!!


On 8/2/2022 11:19 AM, Daniel P. Berrangé wrote:

On Mon, Aug 01, 2022 at 11:03:49AM -0500, Praveen K Paladugu wrote:

Folks,

We are implementing Live Migration support in "ch" driver of Libvirt. I'd
like to confirm if the approach we have chosen would be accepted upstream
once implemented.


Our immediate goal is to implement "Hypervisor Native" + "Managed Direct"
mode of migration. "Hypervisor Native" here referring to VMM(ch) being
responsible for data flow. This in contrast to TUNNELED migration where data
is sent over libvirt rpc.


Avoiding TUNNELLED migration is a very good idea. This was a short term
hack to workaround the lack of TLS support in QEMU. It is more efficient
to have TLS natively integrated in the hypervisor layer than libvirt.

IOW, "Hypervisor native" is a good choice.



"Managed Direct" referring to virsh client responsible for control flow
between source and dest hosts. The libvirtd daemons on source and
destination do not have to communicate with each other. These modes are
described further at
https://libvirt.org/migration.html#network-data-transports.


I'd caution that I think 'managed direct' migration leaves you with
fewer nice options for ensuring resilience of the migration.

IOW, if the client application goes away, I think it'll be harder
for the libvirt CH driver to recover from that scenario.

Also if a client app is using the DigitalOcean 'go-libvirt' API
instead of our 'libvit-go-module' API, things are even more
limited since thg 'go-libvirt' API directly speaks to the RPC
protocol, bypassing libvirt.so logic related to migration
process steps.

With the peer-to-peer mode, migration can carry on even if the
client app goes away, since the client app isn't a part of the
control loop.

So overall, I'd encourage peer-to-peer migration as the preferrable
option, unless you can hand-off absolutely everything to the CH
code and not have libvirt involved in orchestrating the migration
steps at all ?
Makes sense to prioritize peer-to-peer migration. Our current project is 
an internship and has strict time constraints. As we are well under way 
for "Managed Direct" mode, we will finish this and focus on peer-to-peer 
migration mode right after.
  

At the moment, Cloud-Hypervisor supports receiving migration data only on
Unix Domain Sockets. Also, Cloud-Hypervisor does not encrypt the VM data
while sending.


Hmm, that's quite limiting.



We are considering forking "socat" processes as documented at 
https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/live_migration.md.
The socat processes will be forked in "Prepare" and "Perform" phases on
Destination and Source hosts respectively.

I couldn't find any existing implementation in libvirt to connect Domain
Sockets on different hosts. Please let me know, if you'd recommend a
different approach from forking socat processes to connect Domain Sockets on
source and dest hosts to allow Live VM Migration.


I think building something around socat will get you going quickly, but
ultimately be harmful over the long term.
Makes sense. We were also concerned about long term maintenance so 
wanted to check on this mailing list. As there isn't better mechanism to 
connect domain sockets on source and dest hosts, we will finish up the 
"socat" based implementation and get it to work end-to-end.


Our experiance with QEMU has been that to maximise performance you need
the lowest level in full control. These days QEMU can open multiple TCP
connections concurrently from multiple, so that throughput isn't limited
by data copy performance of a single CPU. It also has ability to take
advantage of kernel features like zerocopy. Use of an socat proxy is
going to add many data copies to the transport which can only harm your
performance.

So my recommendation would be to invest time in first extending CH so
that it natively supports opening TCP connections, and then take advantage
of that in libvirt from the start. You then have the basic foundation
right on which to add stuff like TLS, zerocopy, multi-conection, and more


Again, thanks for the details and the recommendation. Enabling TCP 
connections and other low-level features in cloud-hypervisor isn't 
something we can tackle within our current time constraints. But will 
follow up with cloud-hypervisor community and open a tracking issue for 
this work.



With regards,
Daniel


--
Regards,
Praveen K Paladugu



Re: [libvirt PATCH 2/2] conf: set the default chr device type to pty

2022-08-02 Thread Praveen K Paladugu




On 8/1/2022 8:01 AM, Peter Krempa wrote:

On Fri, Jul 29, 2022 at 20:36:57 +, Praveen K Paladugu wrote:

explicitly set the chr device type to pty to pass the
checks of ch driver.
https://gitlab.com/libvirt/libvirt/-/issues/344


This is not a persuading enough enough commit message ...



Signed-off-by: Praveen K Paladugu 
---
  src/conf/domain_conf.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e85cc1f809..abe9d8ae08 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10078,6 +10078,7 @@ virDomainChrSourceDefNew(virDomainXMLOption *xmlopt)
  
  if (!(def = virObjectNew(virDomainChrSourceDefClass)))

  return NULL;
+def->type = VIR_DOMAIN_CHR_TYPE_PTY;


... to justify a global change like this.

Could you please at least clarify which code path is problematic? I see
e.g. that virDomainChrDefParseXML sets VIR_DOMAIN_CHR_TYPE_PTY as the
source type if the user doesn't set one.


To summarize the issue, a post parsing step appends a stub console via
virDomainDefAddConsoleCompat to Guest Domain XML. Below is the trace for 
how the stub console is added.
virDomainDefPostParse -> virDomainDefPostParseCommon -> 
virDomainDefAddImplicitDevices -> virDomainDefAddConsoleCompat


The stub console added in virDomainDefAddConsoleCompat is initialized to 
type VIR_DOMAIN_CHR_TYPE_NULL, when a zero_intialized console object is 
created.


Cloud-Hypervisor driver's deviceValidateCallback 
(chValidateDomainDeviceDef) checks that the type of stub console is not 
VIR_DOMAIN_CHR_TYPE_PTY and returns an error.


Because of the above sequence of steps, cloud-hypervisor VMs fail to be 
created with the following error:


$ virsh -c ch:///system create /files/ch-impish.xml
error: Failed to create domain from /nfs/ch-impish.xml
error: internal error: Console can only be enabled for a PTY


If this is a workaround for the stub console added by default in
virDomainDefAddConsoleCompat and the cloud hypervisor e.g. doesn't need
that or it's wrong for it's usage, the modification shoud IMO be limited
to the cloud hypervisor similarly to what I suggested in the issue.



By running a test Qemu VM, I verified that virDomainDefAddConsoleCompat 
is adding a console of type PTY. By passing below serial device 
configuration for a Qemu VM:


 

 

I see the below stub console being added:

$ virsh dumpxml qemu_impish

...

  
  

  
  


  
  
  

...


So, I wanted to check if setting the default chr device to PTY makes sense.


Thinking further, it makes sense to limit the change to "ch" driver 
only. I will send out an updated patch with the suggested change. Hope 
the above details provide enough context on the source of the issue.



Note that we require commit messages to be self-explanatory without
refering to e.g. outside discussions.


Thanks, will add all relevant details in the commit message itself, in 
my next revision.


--
Regards,
Praveen K Paladugu



Live migration support for Cloud-Hypervisor VMs

2022-08-01 Thread Praveen K Paladugu

Folks,

We are implementing Live Migration support in "ch" driver of Libvirt. 
I'd like to confirm if the approach we have chosen would be accepted 
upstream once implemented.



Our immediate goal is to implement "Hypervisor Native" + "Managed 
Direct" mode of migration. "Hypervisor Native" here referring to VMM(ch) 
being responsible for data flow. This in contrast to TUNNELED migration 
where data is sent over libvirt rpc.


"Managed Direct" referring to virsh client responsible for control flow 
between source and dest hosts. The libvirtd daemons on source and 
destination do not have to communicate with each other. These modes are 
described further at 
https://libvirt.org/migration.html#network-data-transports.



At the moment, Cloud-Hypervisor supports receiving migration data only 
on Unix Domain Sockets. Also, Cloud-Hypervisor does not encrypt the VM 
data while sending.


We are considering forking "socat" processes as documented at 
https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/live_migration.md. 
The socat processes will be forked in "Prepare" and "Perform" phases on 
Destination and Source hosts respectively.


I couldn't find any existing implementation in libvirt to connect Domain 
Sockets on different hosts. Please let me know, if you'd recommend a 
different approach from forking socat processes to connect Domain 
Sockets on source and dest hosts to allow Live VM Migration.


FYI, I had an early discussion on this topic at 
https://gitlab.com/libvirt/libvirt/-/issues/352 and Peter suggested I 
follow here for broader discussion. Also Peter, rightly, suggested we 
look at enabling encryption of VM data in cloud-hypervisor. This is 
something we will follow up with after enabling Live Migration in Libvirt.


--
Regards,
Praveen K Paladugu



[libvirt PATCH 1/2] ch: drop the check to have a single console/serial

2022-07-29 Thread Praveen K Paladugu
Starting with version 18.0, cloud-hypervisor supports a console
and a serial device in parallel.
https://github.com/cloud-hypervisor/cloud-hypervisor/issues/3012

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index ae53c6fe05..bf687a6c32 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -281,14 +281,7 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
 return -1;
 }
 
-if ((def->nconsoles &&
- def->consoles[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)
-&& (def->nserials &&
-def->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY)) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Only a single console or serial can be configured 
for this domain"));
-return -1;
-} else if (def->nconsoles > 1) {
+if (def->nconsoles > 1) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Only a single console can be configured for this 
domain"));
 return -1;
-- 
2.27.0



[libvirt PATCH 2/2] conf: set the default chr device type to pty

2022-07-29 Thread Praveen K Paladugu
explicitly set the chr device type to pty to pass the
checks of ch driver.
https://gitlab.com/libvirt/libvirt/-/issues/344

Signed-off-by: Praveen K Paladugu 
---
 src/conf/domain_conf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e85cc1f809..abe9d8ae08 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10078,6 +10078,7 @@ virDomainChrSourceDefNew(virDomainXMLOption *xmlopt)
 
 if (!(def = virObjectNew(virDomainChrSourceDefClass)))
 return NULL;
+def->type = VIR_DOMAIN_CHR_TYPE_PTY;
 
 if (xmlopt && xmlopt->privateData.chrSourceNew &&
 !(def->privateData = xmlopt->privateData.chrSourceNew())) {
-- 
2.27.0



[libvirt PATCH 0/2] fix console device access in ch driver

2022-07-29 Thread Praveen K Paladugu
Patch1:
Drops the check to only have a console/serial device configured
for ch VMs. This is no longer needed.

Patch2:
Addresses https://gitlab.com/libvirt/libvirt/-/issues/344. Libvirt adds compat
console devices for "hvm" VMs. The added console/serial device type is
initialized to VIR_DOMAIN_CHR_TYPE_NULL, when in fact the device added is a pty
device. This patch modifies the default console device type to "pty".

I looked at NOT adding Compat Console devices for ch VMs. But this looked like
a better fix.

Praveen K Paladugu (2):
  ch: drop the check to have a single console/serial
  conf: set the default chr device type to pty

 src/ch/ch_domain.c | 9 +
 src/conf/domain_conf.c | 1 +
 2 files changed, 2 insertions(+), 8 deletions(-)

-- 
2.27.0



Re: [libvirt PATCH v5 0/7] cgroup and thread management in ch driver

2022-02-01 Thread Praveen K Paladugu




On 1/28/2022 10:05 AM, Michal Prívozník wrote:

On 1/25/22 17:19, Praveen K Paladugu wrote:

This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.



And also does a lot of formatting changes back and forth. I'm not fond
of that really. If you want to clean up the formatting please do so in a
separate patch(set).


Michal,

My apologies for the churn related to formatting. I ran "GNU intend" 
these patches assuming that would correctly handle all the formatting.

That caused a ton of formatting issues, I tried to revert most of it.

Seems like I missed a few instances. I will pay attention to the 
formatting in the follow up submissions.



I took note of Persistent Def and handling of NUMA Nodeset in 
cloud-hypervisor. The original author for this patch is no longer with 
Microsoft. I will take some time to figure this out and submit patches 
are necessary.


Appreciate your support with merging this patch set.





  src/ch/ch_conf.c   |   2 +
  src/ch/ch_conf.h   |   4 +-
  src/ch/ch_domain.c |  64 
  src/ch/ch_domain.h |  18 +-
  src/ch/ch_driver.c | 590 +
  src/ch/ch_monitor.c| 156 +
  src/ch/ch_monitor.h|  56 +++-
  src/ch/ch_process.c| 385 -
  src/ch/ch_process.h|   3 +
  src/hypervisor/domain_cgroup.c | 457 -
  src/hypervisor/domain_cgroup.h |  72 
  src/libvirt_private.syms   |  14 +-
  src/qemu/qemu_cgroup.c | 413 +--
  src/qemu/qemu_cgroup.h |  11 -
  src/qemu/qemu_driver.c |  14 +-
  src/qemu/qemu_hotplug.c|   7 +-
  src/qemu/qemu_process.c|  24 +-
  17 files changed, 1835 insertions(+), 455 deletions(-)



Nevertheless, I'm fixing all the issues I've raised and merging.




Reviewed-by: Michal Privoznik 

Michal


--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH v5 0/7] cgroup and thread management in ch driver

2022-01-28 Thread Praveen K Paladugu

Ping..

If this patch set is ready to be merged, I'd like to get started on next 
set.


Thank you,
Praveen K Paladugu


On 1/25/2022 10:19 AM, Praveen K Paladugu wrote:

This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

v5:
* bumped the verion of callbacks in ch driver to 8.1.0

v4:
* addressed all open comments in v3
* dropped all the merged commits

v3:
* addrressed all the formatting comments in v2 patch set
* dropped indentation patches are they do not adhere to libvirt coding style
* fixed build issue in qemu driver that was introduced in v2

Praveen K Paladugu (3):
   qemu,hypervisor: refactor some cgroup mgmt methods
   ch_process: Setup emulator and iothread settings
   ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (4):
   ch: methods for cgroup mgmt in ch driver
   ch_driver,ch_domain: vcpupin callback in ch driver
   ch_driver: enable typed param string for numatune
   ch_driver: add numatune callbacks for CH driver

  src/ch/ch_conf.c   |   2 +
  src/ch/ch_conf.h   |   4 +-
  src/ch/ch_domain.c |  64 
  src/ch/ch_domain.h |  18 +-
  src/ch/ch_driver.c | 590 +
  src/ch/ch_monitor.c| 156 +
  src/ch/ch_monitor.h|  56 +++-
  src/ch/ch_process.c| 385 -
  src/ch/ch_process.h|   3 +
  src/hypervisor/domain_cgroup.c | 457 -
  src/hypervisor/domain_cgroup.h |  72 
  src/libvirt_private.syms   |  14 +-
  src/qemu/qemu_cgroup.c | 413 +--
  src/qemu/qemu_cgroup.h |  11 -
  src/qemu/qemu_driver.c |  14 +-
  src/qemu/qemu_hotplug.c|   7 +-
  src/qemu/qemu_process.c|  24 +-
  17 files changed, 1835 insertions(+), 455 deletions(-)



--
Regards,
Praveen K Paladugu



[libvirt PATCH v5 4/7] ch_driver: enable typed param string for numatune

2022-01-25 Thread Praveen K Paladugu
From: Vineeth Pillai 

Enable support of VIR_DRV_FEATURE_TYPED_PARAM_STRING to enable numatune

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 956189e83f..32ae15f940 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -943,6 +943,36 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+/* Which features are supported by this driver? */
+static int
+chConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+return -1;
+
+switch ((virDrvFeature) feature) {
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
+}
+}
+
 static int
 chDomainGetVcpusFlags(virDomainPtr dom,
   unsigned int flags)
@@ -1285,6 +1315,7 @@ static virHypervisorDriver chHypervisorDriver = {
 .connectListAllDomains = chConnectListAllDomains,   /* 7.5.0 */
 .connectListDomains = chConnectListDomains, /* 7.5.0 */
 .connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
+.connectSupportsFeature = chConnectSupportsFeature, /* 8.1.0 */
 .domainCreateXML = chDomainCreateXML,   /* 7.5.0 */
 .domainCreate = chDomainCreate, /* 7.5.0 */
 .domainCreateWithFlags = chDomainCreateWithFlags,   /* 7.5.0 */
-- 
2.27.0




[libvirt PATCH v5 0/7] cgroup and thread management in ch driver

2022-01-25 Thread Praveen K Paladugu
This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

v5:
* bumped the verion of callbacks in ch driver to 8.1.0

v4:
* addressed all open comments in v3
* dropped all the merged commits

v3:
* addrressed all the formatting comments in v2 patch set
* dropped indentation patches are they do not adhere to libvirt coding style
* fixed build issue in qemu driver that was introduced in v2

Praveen K Paladugu (3):
  qemu,hypervisor: refactor some cgroup mgmt methods
  ch_process: Setup emulator and iothread settings
  ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (4):
  ch: methods for cgroup mgmt in ch driver
  ch_driver,ch_domain: vcpupin callback in ch driver
  ch_driver: enable typed param string for numatune
  ch_driver: add numatune callbacks for CH driver

 src/ch/ch_conf.c   |   2 +
 src/ch/ch_conf.h   |   4 +-
 src/ch/ch_domain.c |  64 
 src/ch/ch_domain.h |  18 +-
 src/ch/ch_driver.c | 590 +
 src/ch/ch_monitor.c| 156 +
 src/ch/ch_monitor.h|  56 +++-
 src/ch/ch_process.c| 385 -
 src/ch/ch_process.h|   3 +
 src/hypervisor/domain_cgroup.c | 457 -
 src/hypervisor/domain_cgroup.h |  72 
 src/libvirt_private.syms   |  14 +-
 src/qemu/qemu_cgroup.c | 413 +--
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  24 +-
 17 files changed, 1835 insertions(+), 455 deletions(-)

-- 
2.27.0




[libvirt PATCH v5 1/7] qemu, hypervisor: refactor some cgroup mgmt methods

2022-01-25 Thread Praveen K Paladugu
Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared with ch driver for cgroup management.

Signed-off-by: Praveen K Paladugu 
---
 src/hypervisor/domain_cgroup.c | 457 -
 src/hypervisor/domain_cgroup.h |  72 ++
 src/libvirt_private.syms   |  14 +-
 src/qemu/qemu_cgroup.c | 413 +
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  24 +-
 8 files changed, 580 insertions(+), 432 deletions(-)

diff --git a/src/hypervisor/domain_cgroup.c b/src/hypervisor/domain_cgroup.c
index 61b54f071c..05c53ff7d1 100644
--- a/src/hypervisor/domain_cgroup.c
+++ b/src/hypervisor/domain_cgroup.c
@@ -22,11 +22,12 @@
 
 #include "domain_cgroup.h"
 #include "domain_driver.h"
-
+#include "util/virnuma.h"
+#include "virlog.h"
 #include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
-
+VIR_LOG_INIT("domain.cgroup");
 
 int
 virDomainCgroupSetupBlkio(virCgroup *cgroup, virDomainBlkiotune blkio)
@@ -269,3 +270,455 @@ virDomainCgroupSetMemoryLimitParameters(virCgroup *cgroup,
 
 return 0;
 }
+
+
+int
+virDomainCgroupSetupBlkioCgroup(virDomainObj *vm,
+virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
+if (vm->def->blkio.weight || vm->def->blkio.ndevices) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Block I/O tuning is not available on this 
host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupBlkio(cgroup, vm->def->blkio);
+}
+
+
+int
+virDomainCgroupSetupMemoryCgroup(virDomainObj *vm,
+ virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
+if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Memory cgroup is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupMemtune(cgroup, vm->def->mem);
+}
+
+
+int
+virDomainCgroupSetupCpusetCgroup(virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
+return 0;
+
+if (virCgroupSetCpusetMemoryMigrate(cgroup, true) < 0)
+return -1;
+
+return 0;
+}
+
+
+int
+virDomainCgroupSetupCpuCgroup(virDomainObj *vm,
+  virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
+if (vm->def->cputune.sharesSpecified) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("CPU tuning is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+if (vm->def->cputune.sharesSpecified) {
+
+if (virCgroupSetCpuShares(cgroup, vm->def->cputune.shares) < 0)
+return -1;
+
+}
+
+return 0;
+}
+
+
+int
+virDomainCgroupInitCgroup(const char *prefix,
+  virDomainObj * vm,
+  size_t nnicindexes,
+  int *nicindexes,
+  virCgroup * cgroup,
+  int cgroupControllers,
+  unsigned int maxThreadsPerProc,
+  bool privileged,
+  char *machineName)
+{
+if (!privileged)
+return 0;
+
+if (!virCgroupAvailable())
+return 0;
+
+virCgroupFree(cgroup);
+cgroup = NULL;
+
+if (!vm->def->resource)
+vm->def->resource = g_new0(virDomainResourceDef, 1);
+
+if (!vm->def->resource->partition)
+vm->def->resource->partition = g_strdup("/machine");
+
+if (!g_path_is_absolute(vm->def->resource->partition)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Resource partition '%s' must start with '/'"),
+   vm->def->resource->partition);
+return -1;
+}
+
+if (virCgroupNewMachine(machineName,
+prefix,
+vm->def->uuid,
+NULL,
+vm->pid,
+false,
+nnicindexes, nicindexes,
+vm->def->

[libvirt PATCH v5 3/7] ch_driver, ch_domain: vcpupin callback in ch driver

2022-01-25 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c  |  30 +
 src/ch/ch_domain.h  |   7 ++-
 src/ch/ch_driver.c  | 145 
 src/ch/ch_monitor.c |   2 +-
 4 files changed, 181 insertions(+), 3 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 6f0cec8c6e..6fde7122f7 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "datatypes.h"
 #include "ch_domain.h"
 #include "domain_driver.h"
 #include "viralloc.h"
@@ -416,3 +417,32 @@ virCHDomainGetMachineName(virDomainObj *vm)
 
 return ret;
 }
+
+/**
+ * virCHDomainObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObj *
+virCHDomainObjFromDomain(virDomainPtr domain)
+{
+virDomainObj *vm;
+virCHDriver *driver = domain->conn->privateData;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+if (!vm) {
+virUUIDFormat(domain->uuid, uuidstr);
+virReportError(VIR_ERR_NO_DOMAIN,
+   _("no domain with matching uuid '%s' (%s)"),
+   uuidstr, domain->name);
+return NULL;
+}
+
+return vm;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index cb94905b94..60a761ac84 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -97,5 +97,8 @@ virCHDomainGetVcpuPid(virDomainObj *vm,
 bool
 virCHDomainHasVcpuPids(virDomainObj *vm);
 
-char *
-virCHDomainGetMachineName(virDomainObj *vm);
+char
+*virCHDomainGetMachineName(virDomainObj *vm);
+
+virDomainObj
+*virCHDomainObjFromDomain(virDomain *domain);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 53e0872207..956189e83f 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -25,6 +25,7 @@
 #include "ch_driver.h"
 #include "ch_monitor.h"
 #include "ch_process.h"
+#include "domain_cgroup.h"
 #include "datatypes.h"
 #include "driver.h"
 #include "viraccessapicheck.h"
@@ -1129,6 +1130,148 @@ chDomainGetVcpus(virDomainPtr dom,
 return ret;
 }
 
+static int
+chDomainPinVcpuLive(virDomainObj *vm,
+virDomainDef *def,
+int vcpu,
+virCHDriver *driver,
+virCHDriverConfig *cfg,
+virBitmap *cpumap)
+{
+g_autoptr(virBitmap) tmpmap = NULL;
+g_autoptr(virCgroup) cgroup_vcpu = NULL;
+virDomainVcpuDef *vcpuinfo;
+virCHDomainObjPrivate *priv = vm->privateData;
+
+g_autofree char *str = NULL;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("vcpu %d is out of range of live cpu count %d"),
+   vcpu, virDomainDefGetVcpusMax(def));
+return -1;
+}
+
+if (!(tmpmap = virBitmapNewCopy(cpumap)))
+return -1;
+
+if (!(str = virBitmapFormat(cpumap)))
+return -1;
+
+if (vcpuinfo->online) {
+/* Configure the corresponding cpuset cgroup before set affinity. */
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
+   false, &cgroup_vcpu) < 0)
+return -1;
+if (virDomainCgroupSetupCpusetCpus(cgroup_vcpu, cpumap) < 0)
+return -1;
+}
+
+if (virProcessSetAffinity(virCHDomainGetVcpuPid(vm, vcpu), cpumap, 
false) < 0)
+return -1;
+}
+
+virBitmapFree(vcpuinfo->cpumask);
+vcpuinfo->cpumask = tmpmap;
+tmpmap = NULL;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+return -1;
+
+return 0;
+}
+
+
+static int
+chDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virBitmap *pcpumap = NULL;
+virDomainVcpuDef *vcpuinfo = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_

[libvirt PATCH v5 6/7] ch_process: Setup emulator and iothread settings

2022-01-25 Thread Praveen K Paladugu
using virCHProcessSetupPid

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 60 +++
 src/ch/ch_monitor.h |  2 ++
 src/ch/ch_process.c | 77 -
 3 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 6c1d889a82..2a7cffb696 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -930,3 +930,63 @@ virCHMonitorGetInfo(virCHMonitor *mon, virJSONValue **info)
 {
 return virCHMonitorGet(mon, URL_VM_INFO, info);
 }
+
+/**
+ * virCHMonitorGetIOThreads:
+ * @mon: Pointer to the monitor
+ * @iothreads: Location to return array of IOThreadInfo data
+ *
+ * Retrieve the list of iothreads defined/running for the machine
+ *
+ * Returns count of IOThreadInfo structures on success
+ *-1 on error.
+ */
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+ virDomainIOThreadInfo ***iothreads)
+{
+size_t nthreads = 0, niothreads = 0;
+int thd_index;
+virDomainIOThreadInfo **iothreadinfolist = NULL, *iothreadinfo = NULL;
+
+*iothreads = NULL;
+nthreads = virCHMonitorRefreshThreadInfo(mon);
+
+iothreadinfolist = g_new0(virDomainIOThreadInfo*, nthreads);
+
+for (thd_index = 0; thd_index < nthreads; thd_index++) {
+virBitmap *map = NULL;
+if (mon->threads[thd_index].type == virCHThreadTypeIO) {
+iothreadinfo = g_new0(virDomainIOThreadInfo, 1);
+
+iothreadinfo->iothread_id = mon->threads[thd_index].ioInfo.tid;
+
+if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
+goto cleanup;
+
+if (virBitmapToData(map, &(iothreadinfo->cpumap),
+&(iothreadinfo->cpumaplen)) < 0) {
+virBitmapFree(map);
+goto cleanup;
+}
+virBitmapFree(map);
+/* Append to iothreadinfolist */
+iothreadinfolist[niothreads] = iothreadinfo;
+niothreads++;
+}
+}
+VIR_DELETE_ELEMENT_INPLACE(iothreadinfolist,
+   niothreads, nthreads);
+*iothreads = iothreadinfolist;
+VIR_DEBUG("niothreads = %ld", niothreads);
+return niothreads;
+
+cleanup:
+if (iothreadinfolist) {
+for (thd_index = 0; thd_index < niothreads; thd_index++)
+VIR_FREE(iothreadinfolist[thd_index]);
+VIR_FREE(iothreadinfolist);
+}
+if (iothreadinfo)
+VIR_FREE(iothreadinfo);
+return -1;
+}
diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h
index 6646316454..ffc80e8910 100644
--- a/src/ch/ch_monitor.h
+++ b/src/ch/ch_monitor.h
@@ -119,3 +119,5 @@ int virCHMonitorGetCPUInfo(virCHMonitor *mon,
size_t maxvcpus);
 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh,
  virCHMonitorThreadInfo **threads);
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+ virDomainIOThreadInfo ***iothreads);
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 1a0730a4d1..2b81c9f757 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -41,7 +41,6 @@ VIR_LOG_INIT("ch.ch_process");
 #define START_VM_POSTFIX ": starting up vm\n"
 
 
-
 static virCHMonitor *
 virCHProcessConnectMonitor(virCHDriver *driver,
virDomainObj *vm)
@@ -310,6 +309,74 @@ virCHProcessSetupPid(virDomainObj *vm,
 return ret;
 }
 
+static int
+virCHProcessSetupIOThread(virDomainObj *vm,
+  virDomainIOThreadInfo *iothread)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+return virCHProcessSetupPid(vm, iothread->iothread_id,
+VIR_CGROUP_THREAD_IOTHREAD,
+iothread->iothread_id,
+priv->autoCpuset, /* This should be updated 
when CLH supports accepting
+  iothread settings from input domain 
definition */
+vm->def->cputune.iothread_period,
+vm->def->cputune.iothread_quota,
+NULL); /* CLH doesn't allow choosing a 
scheduler for iothreads.*/
+}
+
+static int
+virCHProcessSetupIOThreads(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+virDomainIOThreadInfo **iothreads = NULL;
+size_t i;
+size_t  niothreads;
+
+niothreads = virCHMonitorGetIOThreads(priv->monitor, &iothreads);
+for (i = 0; i < niothreads; i++) {
+VIR_DEBUG("IOThread index = %ld , tid = %d", i, 
iothreads[i]->iothread_id);
+if (virCHProcessSetupIOThread(vm, iothreads[i]) < 0)
+return -1;
+}
+return 0;
+}
+
+
+static int
+virC

[libvirt PATCH v5 2/7] ch: methods for cgroup mgmt in ch driver

2022-01-25 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c|   2 +
 src/ch/ch_conf.h|   4 +-
 src/ch/ch_domain.c  |  34 +
 src/ch/ch_domain.h  |  11 +-
 src/ch/ch_monitor.c |  96 ++
 src/ch/ch_monitor.h |  54 +++-
 src/ch/ch_process.c | 308 ++--
 src/ch/ch_process.h |   3 +
 8 files changed, 492 insertions(+), 20 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index 98f1e89003..be12934dcd 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -125,6 +125,8 @@ virCHDriverConfigNew(bool privileged)
 if (!(cfg = virObjectNew(virCHDriverConfigClass)))
 return NULL;
 
+cfg->cgroupControllers = -1; /* Auto detect */
+
 if (privileged) {
 if (virGetUserID(CH_USER, &cfg->user) < 0)
 return NULL;
diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 8fe69c8545..1790295ede 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -35,11 +35,13 @@ struct _virCHDriverConfig {
 
 char *stateDir;
 char *logDir;
-
+int cgroupControllers;
 uid_t user;
 gid_t group;
 };
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCHDriverConfig, virObjectUnref);
+
 struct _virCHDriver
 {
 virMutex lock;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index a746d0f5fd..6f0cec8c6e 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -319,6 +319,40 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
_("Serial can only be enabled for a PTY"));
 return -1;
 }
+return 0;
+}
+
+int
+virCHDomainRefreshThreadInfo(virDomainObj *vm)
+{
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virCHMonitorThreadInfo *info = NULL;
+size_t nthreads, ncpus = 0;
+size_t i;
+
+nthreads = virCHMonitorGetThreadInfo(virCHDomainGetMonitor(vm),
+ true, &info);
+
+for (i = 0; i < nthreads; i++) {
+virCHDomainVcpuPrivate *vcpupriv;
+virDomainVcpuDef *vcpu;
+virCHMonitorCPUInfo *vcpuInfo;
+
+if (info[i].type != virCHThreadTypeVcpu)
+continue;
+
+/* TODO: hotplug support */
+vcpuInfo = &info[i].vcpuInfo;
+vcpu = virDomainDefGetVcpu(vm->def, vcpuInfo->cpuid);
+vcpupriv = CH_DOMAIN_VCPU_PRIVATE(vcpu);
+vcpupriv->tid = vcpuInfo->tid;
+ncpus++;
+}
+
+/* TODO: Remove the warning when hotplug is implemented.*/
+if (ncpus != maxvcpus)
+VIR_WARN("Mismatch in the number of cpus, expected: %ld, actual: %ld",
+ maxvcpus, ncpus);
 
 return 0;
 }
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 4d0b5479b8..cb94905b94 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -53,11 +53,13 @@ typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate;
 struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
-virChrdevs *chrdevs;
-virCHDriver *driver;
-virCHMonitor *monitor;
 char *machineName;
 virBitmap *autoCpuset;
+virBitmap *autoNodeset;
+virCHDriver *driver;
+virCHMonitor *monitor;
+virCgroup *cgroup;
+virChrdevs *chrdevs;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
@@ -87,7 +89,8 @@ void
 virCHDomainObjEndJob(virDomainObj *obj);
 
 int
-virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+virCHDomainRefreshThreadInfo(virDomainObj *vm);
+
 pid_t
 virCHDomainGetVcpuPid(virDomainObj *vm,
   unsigned int vcpuid);
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index a19f0c7e33..d984bf9822 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -41,6 +41,7 @@ VIR_LOG_INIT("ch.ch_monitor");
 
 static virClass *virCHMonitorClass;
 static void virCHMonitorDispose(void *obj);
+static void virCHMonitorThreadInfoFree(virCHMonitor * mon);
 
 static int virCHMonitorOnceInit(void)
 {
@@ -578,6 +579,7 @@ static void virCHMonitorDispose(void *opaque)
 virCHMonitor *mon = opaque;
 
 VIR_DEBUG("mon=%p", mon);
+virCHMonitorThreadInfoFree(mon);
 virObjectUnref(mon->vm);
 }
 
@@ -743,6 +745,100 @@ virCHMonitorGet(virCHMonitor *mon, const char *endpoint, 
virJSONValue **response
 return ret;
 }
 
+static void
+virCHMonitorThreadInfoFree(virCHMonitor *mon)
+{
+mon->nthreads = 0;
+if (mon->threads)
+VIR_FREE(mon->threads);
+}
+
+static size_t
+virCHMonitorRefreshThreadInfo(virCHMonitor *mon)
+{
+virCHMonitorThreadInfo *info = NULL;
+g_autofree pid_t *tids = NULL;
+virDomainObj *vm = mon->vm;
+size_t ntids = 0;
+size_t i;
+
+
+virCHMonitorThreadInfoFree(mon);
+if (virProcessGetPids(vm->pid, &ntids, &tids) < 0) {
+mon->threads = NULL;
+return 0;
+}
+
+info = g_new0(virCHMonitorThreadInfo, ntids);
+for (i = 0; i < ntids; i++) {
+g_autofree 

[libvirt PATCH v5 7/7] ch_driver: emulator threadinfo & pinning callbacks

2022-01-25 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 154 +
 1 file changed, 154 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index d257c025ef..d60ff468f0 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -1303,6 +1303,158 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+
+
+static int
+chDomainGetEmulatorPinInfo(virDomainPtr dom,
+   unsigned char *cpumaps,
+   int maplen,
+   unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virCHDomainObjPrivate *priv;
+bool live;
+int ret = -1;
+virBitmap *cpumask = NULL;
+g_autoptr(virBitmap) bitmap = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live) {
+priv = vm->privateData;
+autoCpuset = priv->autoCpuset;
+}
+if (def->cputune.emulatorpin) {
+cpumask = def->cputune.emulatorpin;
+} else if (def->cpumask) {
+cpumask = def->cpumask;
+} else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+   autoCpuset) {
+cpumask = autoCpuset;
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+cpumask = bitmap;
+}
+
+virBitmapToDataBuf(cpumask, cpumaps, maplen);
+
+ret = 1;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainPinEmulator(virDomainPtr dom,
+unsigned char *cpumap,
+int maplen,
+unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virCgroup *cgroup_emulator = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virCHDomainObjPrivate *priv;
+virBitmap *pcpumap = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+g_autofree char *str = NULL;
+virTypedParameterPtr eventParams = NULL;
+int eventNparams = 0;
+int eventMaxparams = 0;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+cfg = virCHDriverGetConfig(driver);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto endjob;
+
+priv = vm->privateData;
+
+if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
+goto endjob;
+
+if (virBitmapIsAllClear(pcpumap)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty cpu list for pinning"));
+goto endjob;
+}
+
+if (def) {
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
+   0, false, &cgroup_emulator) < 0)
+goto endjob;
+
+if (virDomainCgroupSetupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+goto endjob;
+}
+}
+
+if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
+goto endjob;
+
+virBitmapFree(def->cputune.emulatorpin);
+def->cputune.emulatorpin = NULL;
+
+if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
+goto endjob;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto endjob;
+
+str = virBitmapFormat(pcpumap);
+if (virTypedParamsAddString(&eventParams, &eventNparams,
+&eventMaxparams,
+VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
+str) < 0)
+goto endjob;
+
+}
+
+
+ret = 0;
+
+endjob:
+virCHDomainObjEndJob(vm);
+
+cleanup:
+if (cgroup_emulator)
+virCgroupFree(cgroup_emulator);
+virBitmapFree(pcpumap);
+virDomainObjEndAPI(&vm);
+return ret

[libvirt PATCH v5 5/7] ch_driver: add numatune callbacks for CH driver

2022-01-25 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 260 +
 1 file changed, 260 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 32ae15f940..d257c025ef 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
 #include "viruri.h"
 #include "virutil.h"
 #include "viruuid.h"
+#include "virnuma.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -1302,6 +1303,263 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+  virTypedParameterPtr params,
+  int *nparams,
+  unsigned int flags)
+{
+size_t i;
+virDomainObj *vm = NULL;
+virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+virCHDomainObjPrivate *priv;
+g_autofree char *nodeset = NULL;
+int ret = -1;
+virDomainDef *def = NULL;
+bool live = false;
+virBitmap *autoNodeset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (!(vm = virCHDomainObjFromDomain(dom)))
+return -1;
+priv = vm->privateData;
+
+if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live)
+autoNodeset = priv->autoNodeset;
+
+if ((*nparams) == 0) {
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+goto cleanup;
+}
+
+for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+virMemoryParameterPtr param = ¶ms[i];
+
+switch (i) {
+case 0: /* fill numa mode here */
+ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+VIR_TYPED_PARAM_INT, tmpmode) < 0)
+goto cleanup;
+
+break;
+
+case 1: /* fill numa nodeset here */
+nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, 
-1);
+
+if (!nodeset ||
+virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+VIR_TYPED_PARAM_STRING, nodeset) < 0)
+goto cleanup;
+
+nodeset = NULL;
+break;
+
+/* coverity[dead_error_begin] */
+default:
+break;
+/* should not hit here */
+}
+}
+
+if (*nparams > CH_NB_NUMA_PARAM)
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+  virBitmap *nodeset)
+{
+g_autoptr(virCgroup) cgroup_temp = NULL;
+virCHDomainObjPrivate *priv = vm->privateData;
+g_autofree char *nodeset_str = NULL;
+virDomainNumatuneMemMode mode;
+size_t i = 0;
+
+
+if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
+mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("change of nodeset for running domain requires strict 
numa mode"));
+return -1;
+}
+
+if (!virNumaNodesetIsAvailable(nodeset))
+return -1;
+
+/* Ensure the cpuset string is formatted before passing to cgroup */
+if (!(nodeset_str = virBitmapFormat(nodeset)))
+return -1;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (!vcpu->online)
+continue;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+return 0;
+}
+
+for (i = 0; i < vm->def->niothreadids; i++) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+   vm->def->iothreadids[i]->iothread_id,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+}
+
+/* set nodeset for root cgroup */
+if (vi

[libvirt PATCH v4 6/7] ch_process: Setup emulator and iothread settings

2022-01-11 Thread Praveen K Paladugu
using virCHProcessSetupPid

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 60 +++
 src/ch/ch_monitor.h |  2 ++
 src/ch/ch_process.c | 77 -
 3 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 6c1d889a82..2a7cffb696 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -930,3 +930,63 @@ virCHMonitorGetInfo(virCHMonitor *mon, virJSONValue **info)
 {
 return virCHMonitorGet(mon, URL_VM_INFO, info);
 }
+
+/**
+ * virCHMonitorGetIOThreads:
+ * @mon: Pointer to the monitor
+ * @iothreads: Location to return array of IOThreadInfo data
+ *
+ * Retrieve the list of iothreads defined/running for the machine
+ *
+ * Returns count of IOThreadInfo structures on success
+ *-1 on error.
+ */
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+ virDomainIOThreadInfo ***iothreads)
+{
+size_t nthreads = 0, niothreads = 0;
+int thd_index;
+virDomainIOThreadInfo **iothreadinfolist = NULL, *iothreadinfo = NULL;
+
+*iothreads = NULL;
+nthreads = virCHMonitorRefreshThreadInfo(mon);
+
+iothreadinfolist = g_new0(virDomainIOThreadInfo*, nthreads);
+
+for (thd_index = 0; thd_index < nthreads; thd_index++) {
+virBitmap *map = NULL;
+if (mon->threads[thd_index].type == virCHThreadTypeIO) {
+iothreadinfo = g_new0(virDomainIOThreadInfo, 1);
+
+iothreadinfo->iothread_id = mon->threads[thd_index].ioInfo.tid;
+
+if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
+goto cleanup;
+
+if (virBitmapToData(map, &(iothreadinfo->cpumap),
+&(iothreadinfo->cpumaplen)) < 0) {
+virBitmapFree(map);
+goto cleanup;
+}
+virBitmapFree(map);
+/* Append to iothreadinfolist */
+iothreadinfolist[niothreads] = iothreadinfo;
+niothreads++;
+}
+}
+VIR_DELETE_ELEMENT_INPLACE(iothreadinfolist,
+   niothreads, nthreads);
+*iothreads = iothreadinfolist;
+VIR_DEBUG("niothreads = %ld", niothreads);
+return niothreads;
+
+cleanup:
+if (iothreadinfolist) {
+for (thd_index = 0; thd_index < niothreads; thd_index++)
+VIR_FREE(iothreadinfolist[thd_index]);
+VIR_FREE(iothreadinfolist);
+}
+if (iothreadinfo)
+VIR_FREE(iothreadinfo);
+return -1;
+}
diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h
index 6646316454..ffc80e8910 100644
--- a/src/ch/ch_monitor.h
+++ b/src/ch/ch_monitor.h
@@ -119,3 +119,5 @@ int virCHMonitorGetCPUInfo(virCHMonitor *mon,
size_t maxvcpus);
 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh,
  virCHMonitorThreadInfo **threads);
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+ virDomainIOThreadInfo ***iothreads);
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 1a0730a4d1..2b81c9f757 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -41,7 +41,6 @@ VIR_LOG_INIT("ch.ch_process");
 #define START_VM_POSTFIX ": starting up vm\n"
 
 
-
 static virCHMonitor *
 virCHProcessConnectMonitor(virCHDriver *driver,
virDomainObj *vm)
@@ -310,6 +309,74 @@ virCHProcessSetupPid(virDomainObj *vm,
 return ret;
 }
 
+static int
+virCHProcessSetupIOThread(virDomainObj *vm,
+  virDomainIOThreadInfo *iothread)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+return virCHProcessSetupPid(vm, iothread->iothread_id,
+VIR_CGROUP_THREAD_IOTHREAD,
+iothread->iothread_id,
+priv->autoCpuset, /* This should be updated 
when CLH supports accepting
+  iothread settings from input domain 
definition */
+vm->def->cputune.iothread_period,
+vm->def->cputune.iothread_quota,
+NULL); /* CLH doesn't allow choosing a 
scheduler for iothreads.*/
+}
+
+static int
+virCHProcessSetupIOThreads(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+virDomainIOThreadInfo **iothreads = NULL;
+size_t i;
+size_t  niothreads;
+
+niothreads = virCHMonitorGetIOThreads(priv->monitor, &iothreads);
+for (i = 0; i < niothreads; i++) {
+VIR_DEBUG("IOThread index = %ld , tid = %d", i, 
iothreads[i]->iothread_id);
+if (virCHProcessSetupIOThread(vm, iothreads[i]) < 0)
+return -1;
+}
+return 0;
+}
+
+
+static int
+virC

[libvirt PATCH v4 4/7] ch_driver: enable typed param string for numatune

2022-01-11 Thread Praveen K Paladugu
From: Vineeth Pillai 

Enable support of VIR_DRV_FEATURE_TYPED_PARAM_STRING to enable numatune

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 110c86168a..408aae2cd6 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -943,6 +943,36 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+/* Which features are supported by this driver? */
+static int
+chConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+return -1;
+
+switch ((virDrvFeature) feature) {
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
+}
+}
+
 static int
 chDomainGetVcpusFlags(virDomainPtr dom,
   unsigned int flags)
@@ -1285,6 +1315,7 @@ static virHypervisorDriver chHypervisorDriver = {
 .connectListAllDomains = chConnectListAllDomains,   /* 7.5.0 */
 .connectListDomains = chConnectListDomains, /* 7.5.0 */
 .connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
+.connectSupportsFeature = chConnectSupportsFeature, /* 8.0.0 */
 .domainCreateXML = chDomainCreateXML,   /* 7.5.0 */
 .domainCreate = chDomainCreate, /* 7.5.0 */
 .domainCreateWithFlags = chDomainCreateWithFlags,   /* 7.5.0 */
-- 
2.27.0




[libvirt PATCH v4 1/7] qemu, hypervisor: refactor some cgroup mgmt methods

2022-01-11 Thread Praveen K Paladugu
Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared with ch driver for cgroup management.

Signed-off-by: Praveen K Paladugu 
---
 src/hypervisor/domain_cgroup.c | 457 -
 src/hypervisor/domain_cgroup.h |  72 ++
 src/libvirt_private.syms   |  14 +-
 src/qemu/qemu_cgroup.c | 413 +
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  24 +-
 8 files changed, 580 insertions(+), 432 deletions(-)

diff --git a/src/hypervisor/domain_cgroup.c b/src/hypervisor/domain_cgroup.c
index 61b54f071c..05c53ff7d1 100644
--- a/src/hypervisor/domain_cgroup.c
+++ b/src/hypervisor/domain_cgroup.c
@@ -22,11 +22,12 @@
 
 #include "domain_cgroup.h"
 #include "domain_driver.h"
-
+#include "util/virnuma.h"
+#include "virlog.h"
 #include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
-
+VIR_LOG_INIT("domain.cgroup");
 
 int
 virDomainCgroupSetupBlkio(virCgroup *cgroup, virDomainBlkiotune blkio)
@@ -269,3 +270,455 @@ virDomainCgroupSetMemoryLimitParameters(virCgroup *cgroup,
 
 return 0;
 }
+
+
+int
+virDomainCgroupSetupBlkioCgroup(virDomainObj *vm,
+virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
+if (vm->def->blkio.weight || vm->def->blkio.ndevices) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Block I/O tuning is not available on this 
host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupBlkio(cgroup, vm->def->blkio);
+}
+
+
+int
+virDomainCgroupSetupMemoryCgroup(virDomainObj *vm,
+ virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
+if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Memory cgroup is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupMemtune(cgroup, vm->def->mem);
+}
+
+
+int
+virDomainCgroupSetupCpusetCgroup(virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
+return 0;
+
+if (virCgroupSetCpusetMemoryMigrate(cgroup, true) < 0)
+return -1;
+
+return 0;
+}
+
+
+int
+virDomainCgroupSetupCpuCgroup(virDomainObj *vm,
+  virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
+if (vm->def->cputune.sharesSpecified) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("CPU tuning is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+if (vm->def->cputune.sharesSpecified) {
+
+if (virCgroupSetCpuShares(cgroup, vm->def->cputune.shares) < 0)
+return -1;
+
+}
+
+return 0;
+}
+
+
+int
+virDomainCgroupInitCgroup(const char *prefix,
+  virDomainObj * vm,
+  size_t nnicindexes,
+  int *nicindexes,
+  virCgroup * cgroup,
+  int cgroupControllers,
+  unsigned int maxThreadsPerProc,
+  bool privileged,
+  char *machineName)
+{
+if (!privileged)
+return 0;
+
+if (!virCgroupAvailable())
+return 0;
+
+virCgroupFree(cgroup);
+cgroup = NULL;
+
+if (!vm->def->resource)
+vm->def->resource = g_new0(virDomainResourceDef, 1);
+
+if (!vm->def->resource->partition)
+vm->def->resource->partition = g_strdup("/machine");
+
+if (!g_path_is_absolute(vm->def->resource->partition)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Resource partition '%s' must start with '/'"),
+   vm->def->resource->partition);
+return -1;
+}
+
+if (virCgroupNewMachine(machineName,
+prefix,
+vm->def->uuid,
+NULL,
+vm->pid,
+false,
+nnicindexes, nicindexes,
+vm->def->

[libvirt PATCH v4 5/7] ch_driver: add numatune callbacks for CH driver

2022-01-11 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 260 +
 1 file changed, 260 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 408aae2cd6..e3c0ae2952 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
 #include "viruri.h"
 #include "virutil.h"
 #include "viruuid.h"
+#include "virnuma.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -1302,6 +1303,263 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+  virTypedParameterPtr params,
+  int *nparams,
+  unsigned int flags)
+{
+size_t i;
+virDomainObj *vm = NULL;
+virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+virCHDomainObjPrivate *priv;
+g_autofree char *nodeset = NULL;
+int ret = -1;
+virDomainDef *def = NULL;
+bool live = false;
+virBitmap *autoNodeset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (!(vm = virCHDomainObjFromDomain(dom)))
+return -1;
+priv = vm->privateData;
+
+if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live)
+autoNodeset = priv->autoNodeset;
+
+if ((*nparams) == 0) {
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+goto cleanup;
+}
+
+for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+virMemoryParameterPtr param = ¶ms[i];
+
+switch (i) {
+case 0: /* fill numa mode here */
+ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+VIR_TYPED_PARAM_INT, tmpmode) < 0)
+goto cleanup;
+
+break;
+
+case 1: /* fill numa nodeset here */
+nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, 
-1);
+
+if (!nodeset ||
+virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+VIR_TYPED_PARAM_STRING, nodeset) < 0)
+goto cleanup;
+
+nodeset = NULL;
+break;
+
+/* coverity[dead_error_begin] */
+default:
+break;
+/* should not hit here */
+}
+}
+
+if (*nparams > CH_NB_NUMA_PARAM)
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+  virBitmap *nodeset)
+{
+g_autoptr(virCgroup) cgroup_temp = NULL;
+virCHDomainObjPrivate *priv = vm->privateData;
+g_autofree char *nodeset_str = NULL;
+virDomainNumatuneMemMode mode;
+size_t i = 0;
+
+
+if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
+mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("change of nodeset for running domain requires strict 
numa mode"));
+return -1;
+}
+
+if (!virNumaNodesetIsAvailable(nodeset))
+return -1;
+
+/* Ensure the cpuset string is formatted before passing to cgroup */
+if (!(nodeset_str = virBitmapFormat(nodeset)))
+return -1;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (!vcpu->online)
+continue;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+return 0;
+}
+
+for (i = 0; i < vm->def->niothreadids; i++) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+   vm->def->iothreadids[i]->iothread_id,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+}
+
+/* set nodeset for root cgroup */
+if (vi

[libvirt PATCH v4 7/7] ch_driver: emulator threadinfo & pinning callbacks

2022-01-11 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 154 +
 1 file changed, 154 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index e3c0ae2952..bf5bb3696c 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -1303,6 +1303,158 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+
+
+static int
+chDomainGetEmulatorPinInfo(virDomainPtr dom,
+   unsigned char *cpumaps,
+   int maplen,
+   unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virCHDomainObjPrivate *priv;
+bool live;
+int ret = -1;
+virBitmap *cpumask = NULL;
+g_autoptr(virBitmap) bitmap = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live) {
+priv = vm->privateData;
+autoCpuset = priv->autoCpuset;
+}
+if (def->cputune.emulatorpin) {
+cpumask = def->cputune.emulatorpin;
+} else if (def->cpumask) {
+cpumask = def->cpumask;
+} else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+   autoCpuset) {
+cpumask = autoCpuset;
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+cpumask = bitmap;
+}
+
+virBitmapToDataBuf(cpumask, cpumaps, maplen);
+
+ret = 1;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainPinEmulator(virDomainPtr dom,
+unsigned char *cpumap,
+int maplen,
+unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virCgroup *cgroup_emulator = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virCHDomainObjPrivate *priv;
+virBitmap *pcpumap = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+g_autofree char *str = NULL;
+virTypedParameterPtr eventParams = NULL;
+int eventNparams = 0;
+int eventMaxparams = 0;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+cfg = virCHDriverGetConfig(driver);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto endjob;
+
+priv = vm->privateData;
+
+if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
+goto endjob;
+
+if (virBitmapIsAllClear(pcpumap)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty cpu list for pinning"));
+goto endjob;
+}
+
+if (def) {
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
+   0, false, &cgroup_emulator) < 0)
+goto endjob;
+
+if (virDomainCgroupSetupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+goto endjob;
+}
+}
+
+if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
+goto endjob;
+
+virBitmapFree(def->cputune.emulatorpin);
+def->cputune.emulatorpin = NULL;
+
+if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
+goto endjob;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto endjob;
+
+str = virBitmapFormat(pcpumap);
+if (virTypedParamsAddString(&eventParams, &eventNparams,
+&eventMaxparams,
+VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
+str) < 0)
+goto endjob;
+
+}
+
+
+ret = 0;
+
+endjob:
+virCHDomainObjEndJob(vm);
+
+cleanup:
+if (cgroup_emulator)
+virCgroupFree(cgroup_emulator);
+virBitmapFree(pcpumap);
+virDomainObjEndAPI(&vm);
+return ret

[libvirt PATCH v4 3/7] ch_driver, ch_domain: vcpupin callback in ch driver

2022-01-11 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c  |  30 +
 src/ch/ch_domain.h  |   7 ++-
 src/ch/ch_driver.c  | 145 
 src/ch/ch_monitor.c |   2 +-
 4 files changed, 181 insertions(+), 3 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 6f0cec8c6e..6fde7122f7 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "datatypes.h"
 #include "ch_domain.h"
 #include "domain_driver.h"
 #include "viralloc.h"
@@ -416,3 +417,32 @@ virCHDomainGetMachineName(virDomainObj *vm)
 
 return ret;
 }
+
+/**
+ * virCHDomainObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObj *
+virCHDomainObjFromDomain(virDomainPtr domain)
+{
+virDomainObj *vm;
+virCHDriver *driver = domain->conn->privateData;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+if (!vm) {
+virUUIDFormat(domain->uuid, uuidstr);
+virReportError(VIR_ERR_NO_DOMAIN,
+   _("no domain with matching uuid '%s' (%s)"),
+   uuidstr, domain->name);
+return NULL;
+}
+
+return vm;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index cb94905b94..60a761ac84 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -97,5 +97,8 @@ virCHDomainGetVcpuPid(virDomainObj *vm,
 bool
 virCHDomainHasVcpuPids(virDomainObj *vm);
 
-char *
-virCHDomainGetMachineName(virDomainObj *vm);
+char
+*virCHDomainGetMachineName(virDomainObj *vm);
+
+virDomainObj
+*virCHDomainObjFromDomain(virDomain *domain);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 53e0872207..110c86168a 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -25,6 +25,7 @@
 #include "ch_driver.h"
 #include "ch_monitor.h"
 #include "ch_process.h"
+#include "domain_cgroup.h"
 #include "datatypes.h"
 #include "driver.h"
 #include "viraccessapicheck.h"
@@ -1129,6 +1130,148 @@ chDomainGetVcpus(virDomainPtr dom,
 return ret;
 }
 
+static int
+chDomainPinVcpuLive(virDomainObj *vm,
+virDomainDef *def,
+int vcpu,
+virCHDriver *driver,
+virCHDriverConfig *cfg,
+virBitmap *cpumap)
+{
+g_autoptr(virBitmap) tmpmap = NULL;
+g_autoptr(virCgroup) cgroup_vcpu = NULL;
+virDomainVcpuDef *vcpuinfo;
+virCHDomainObjPrivate *priv = vm->privateData;
+
+g_autofree char *str = NULL;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("vcpu %d is out of range of live cpu count %d"),
+   vcpu, virDomainDefGetVcpusMax(def));
+return -1;
+}
+
+if (!(tmpmap = virBitmapNewCopy(cpumap)))
+return -1;
+
+if (!(str = virBitmapFormat(cpumap)))
+return -1;
+
+if (vcpuinfo->online) {
+/* Configure the corresponding cpuset cgroup before set affinity. */
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
+   false, &cgroup_vcpu) < 0)
+return -1;
+if (virDomainCgroupSetupCpusetCpus(cgroup_vcpu, cpumap) < 0)
+return -1;
+}
+
+if (virProcessSetAffinity(virCHDomainGetVcpuPid(vm, vcpu), cpumap, 
false) < 0)
+return -1;
+}
+
+virBitmapFree(vcpuinfo->cpumask);
+vcpuinfo->cpumask = tmpmap;
+tmpmap = NULL;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+return -1;
+
+return 0;
+}
+
+
+static int
+chDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virBitmap *pcpumap = NULL;
+virDomainVcpuDef *vcpuinfo = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_

[libvirt PATCH v4 2/7] ch: methods for cgroup mgmt in ch driver

2022-01-11 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c|   2 +
 src/ch/ch_conf.h|   4 +-
 src/ch/ch_domain.c  |  34 +
 src/ch/ch_domain.h  |  11 +-
 src/ch/ch_monitor.c |  96 ++
 src/ch/ch_monitor.h |  54 +++-
 src/ch/ch_process.c | 308 ++--
 src/ch/ch_process.h |   3 +
 8 files changed, 492 insertions(+), 20 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index 98f1e89003..be12934dcd 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -125,6 +125,8 @@ virCHDriverConfigNew(bool privileged)
 if (!(cfg = virObjectNew(virCHDriverConfigClass)))
 return NULL;
 
+cfg->cgroupControllers = -1; /* Auto detect */
+
 if (privileged) {
 if (virGetUserID(CH_USER, &cfg->user) < 0)
 return NULL;
diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 8fe69c8545..1790295ede 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -35,11 +35,13 @@ struct _virCHDriverConfig {
 
 char *stateDir;
 char *logDir;
-
+int cgroupControllers;
 uid_t user;
 gid_t group;
 };
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCHDriverConfig, virObjectUnref);
+
 struct _virCHDriver
 {
 virMutex lock;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index a746d0f5fd..6f0cec8c6e 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -319,6 +319,40 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
_("Serial can only be enabled for a PTY"));
 return -1;
 }
+return 0;
+}
+
+int
+virCHDomainRefreshThreadInfo(virDomainObj *vm)
+{
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virCHMonitorThreadInfo *info = NULL;
+size_t nthreads, ncpus = 0;
+size_t i;
+
+nthreads = virCHMonitorGetThreadInfo(virCHDomainGetMonitor(vm),
+ true, &info);
+
+for (i = 0; i < nthreads; i++) {
+virCHDomainVcpuPrivate *vcpupriv;
+virDomainVcpuDef *vcpu;
+virCHMonitorCPUInfo *vcpuInfo;
+
+if (info[i].type != virCHThreadTypeVcpu)
+continue;
+
+/* TODO: hotplug support */
+vcpuInfo = &info[i].vcpuInfo;
+vcpu = virDomainDefGetVcpu(vm->def, vcpuInfo->cpuid);
+vcpupriv = CH_DOMAIN_VCPU_PRIVATE(vcpu);
+vcpupriv->tid = vcpuInfo->tid;
+ncpus++;
+}
+
+/* TODO: Remove the warning when hotplug is implemented.*/
+if (ncpus != maxvcpus)
+VIR_WARN("Mismatch in the number of cpus, expected: %ld, actual: %ld",
+ maxvcpus, ncpus);
 
 return 0;
 }
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 4d0b5479b8..cb94905b94 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -53,11 +53,13 @@ typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate;
 struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
-virChrdevs *chrdevs;
-virCHDriver *driver;
-virCHMonitor *monitor;
 char *machineName;
 virBitmap *autoCpuset;
+virBitmap *autoNodeset;
+virCHDriver *driver;
+virCHMonitor *monitor;
+virCgroup *cgroup;
+virChrdevs *chrdevs;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
@@ -87,7 +89,8 @@ void
 virCHDomainObjEndJob(virDomainObj *obj);
 
 int
-virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+virCHDomainRefreshThreadInfo(virDomainObj *vm);
+
 pid_t
 virCHDomainGetVcpuPid(virDomainObj *vm,
   unsigned int vcpuid);
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index a19f0c7e33..d984bf9822 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -41,6 +41,7 @@ VIR_LOG_INIT("ch.ch_monitor");
 
 static virClass *virCHMonitorClass;
 static void virCHMonitorDispose(void *obj);
+static void virCHMonitorThreadInfoFree(virCHMonitor * mon);
 
 static int virCHMonitorOnceInit(void)
 {
@@ -578,6 +579,7 @@ static void virCHMonitorDispose(void *opaque)
 virCHMonitor *mon = opaque;
 
 VIR_DEBUG("mon=%p", mon);
+virCHMonitorThreadInfoFree(mon);
 virObjectUnref(mon->vm);
 }
 
@@ -743,6 +745,100 @@ virCHMonitorGet(virCHMonitor *mon, const char *endpoint, 
virJSONValue **response
 return ret;
 }
 
+static void
+virCHMonitorThreadInfoFree(virCHMonitor *mon)
+{
+mon->nthreads = 0;
+if (mon->threads)
+VIR_FREE(mon->threads);
+}
+
+static size_t
+virCHMonitorRefreshThreadInfo(virCHMonitor *mon)
+{
+virCHMonitorThreadInfo *info = NULL;
+g_autofree pid_t *tids = NULL;
+virDomainObj *vm = mon->vm;
+size_t ntids = 0;
+size_t i;
+
+
+virCHMonitorThreadInfoFree(mon);
+if (virProcessGetPids(vm->pid, &ntids, &tids) < 0) {
+mon->threads = NULL;
+return 0;
+}
+
+info = g_new0(virCHMonitorThreadInfo, ntids);
+for (i = 0; i < ntids; i++) {
+g_autofree 

[libvirt PATCH v4 0/7] cgroup and thread management in ch driver.

2022-01-11 Thread Praveen K Paladugu
This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

v4:
* addressed all open comments in v3
* dropped all the merged commits

v3:
* addrressed all the formatting comments in v2 patch set
* dropped indentation patches are they do not adhere to libvirt coding style
* fixed build issue in qemu driver that was introduced in v2

Praveen K Paladugu (3):
  qemu,hypervisor: refactor some cgroup mgmt methods
  ch_process: Setup emulator and iothread settings
  ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (4):
  ch: methods for cgroup mgmt in ch driver
  ch_driver,ch_domain: vcpupin callback in ch driver
  ch_driver: enable typed param string for numatune
  ch_driver: add numatune callbacks for CH driver

 src/ch/ch_conf.c   |   2 +
 src/ch/ch_conf.h   |   4 +-
 src/ch/ch_domain.c |  64 
 src/ch/ch_domain.h |  18 +-
 src/ch/ch_driver.c | 590 +
 src/ch/ch_monitor.c| 156 +
 src/ch/ch_monitor.h|  56 +++-
 src/ch/ch_process.c| 385 -
 src/ch/ch_process.h|   3 +
 src/hypervisor/domain_cgroup.c | 457 -
 src/hypervisor/domain_cgroup.h |  72 
 src/libvirt_private.syms   |  14 +-
 src/qemu/qemu_cgroup.c | 413 +--
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  24 +-
 17 files changed, 1835 insertions(+), 455 deletions(-)

-- 
2.27.0




Re: [libvirt PATCH v3 00/13] cgroup and thread management in ch driver.

2022-01-05 Thread Praveen K Paladugu

Folks,
I'd like to get this patch set in next release. Bubbling up this thread
as it was sent out before the holidays.

Regards,
Praveen K Paladugu

On 12/10/2021 2:34 PM, Praveen K Paladugu wrote:

This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

v3:
* addrressed all the formatting comments in v2 patch set
* dropped indentation patches are they do not adhere to libvirt coding style
* fixed build issue in qemu driver that was introduced in v2

Praveen K Paladugu (5):
   util: Helper functions to get process info
   ch_driver,ch_domain: vcpu info getter callbacks
   qemu,hypervisor: refactor some cgroup mgmt methods
   ch_process: Setup emulator and iothread settings
   ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (8):
   ch_domain: add virCHDomainGetMonitor helper method
   ch_domain: add methods to manage private vcpu data
   ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap
   ch_monitor: Get nicindexes in prep for cgroup mgmt
   ch: methods for cgroup mgmt in ch driver
   ch_driver,ch_domain: vcpupin callback in ch driver
   ch_driver: enable typed param string for numatune
   ch_driver: add numatune callbacks for CH driver

  src/ch/ch_conf.c   |   2 +
  src/ch/ch_conf.h   |   6 +-
  src/ch/ch_domain.c | 172 ++-
  src/ch/ch_domain.h |  32 +-
  src/ch/ch_driver.c | 789 +
  src/ch/ch_monitor.c| 341 +++---
  src/ch/ch_monitor.h|  60 ++-
  src/ch/ch_process.c| 385 +++-
  src/ch/ch_process.h|   3 +
  src/ch/meson.build |   1 +
  src/hypervisor/domain_cgroup.c | 426 +-
  src/hypervisor/domain_cgroup.h |  52 +++
  src/libvirt_private.syms   |  15 +
  src/qemu/qemu_cgroup.c | 410 +
  src/qemu/qemu_cgroup.h |  11 -
  src/qemu/qemu_driver.c | 130 +-
  src/qemu/qemu_hotplug.c|   7 +-
  src/qemu/qemu_process.c|  20 +-
  src/util/virprocess.c  | 108 +
  src/util/virprocess.h  |   5 +
  20 files changed, 2357 insertions(+), 618 deletions(-)





Re: [libvirt PATCH v2 03/17] ch_domain: fix indentation in ch_domain

2021-12-10 Thread Praveen K Paladugu




On 12/3/2021 11:28 AM, Ján Tomko wrote:

On a Thursday in 2021, Praveen K Paladugu wrote:

Signed-off-by: Praveen K Paladugu 
---
src/ch/ch_domain.c | 130 ++---
1 file changed, 64 insertions(+), 66 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index dd4de9e1ea..44f7d26ca4 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -30,16 +30,12 @@

static int
-virCHDomainObjInitJob(virCHDomainObjPrivate *priv)
+virCHDomainObjInitJob(virCHDomainObjPrivate * priv)


The prevailing style in libvirt codebase is no space after the '*'


Fixed in v3



{
    memset(&priv->job, 0, sizeof(priv->job));




[...]

-    if (def->nserials && def->serials[0]->source->type != 
VIR_DOMAIN_CHR_TYPE_PTY) {

+    if (def->nserials
+    && def->serials[0]->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
   _("Serial can only be enabled for a PTY"));
    return -1;


80 columns is not a hard limit, there's no need to touch this.


Addressed in v3


Jano


--
2.27.0




--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH v2 02/17] util: Helper functions to get process info

2021-12-10 Thread Praveen K Paladugu




On 12/3/2021 11:26 AM, Ján Tomko wrote:

On a Thursday in 2021, Praveen K Paladugu wrote:

Signed-off-by: Praveen K Paladugu 


It would be helpful to say in the commit message that the functions are
being moved, not newly introduced.


Fixed in v3


Jano


---
src/libvirt_private.syms |   2 +
src/qemu/qemu_driver.c   | 116 ++-
src/util/virprocess.c    | 108 
src/util/virprocess.h    |   5 ++
4 files changed, 120 insertions(+), 111 deletions(-)



--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH v2 11/17] qemu, hypervisor: refactor some cgroup mgmt methods

2021-12-10 Thread Praveen K Paladugu




On 12/3/2021 11:38 AM, Ján Tomko wrote:

On a Thursday in 2021, Praveen K Paladugu wrote:

Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared by ch driver for cgroup management.



The QEMU driver fails to compile after this patch - it seems
qemu_process.c needs to include the header with the functions.

To get a build coverage for most of our supported platforms,
you can push into your private fork of the libvirt repo on gitlab.
The pipeline should run automatically.

Thanks for the pointer Jano. I fixed the build issue and also confirmed 
majority of the builds pass in gitlab's CI.



Jano


Signed-off-by: Praveen K Paladugu 
---
src/hypervisor/domain_cgroup.c | 426 -
src/hypervisor/domain_cgroup.h |  52 
src/libvirt_private.syms   |  10 +
src/qemu/qemu_cgroup.c | 410 +--
src/qemu/qemu_cgroup.h |  11 -
src/qemu/qemu_driver.c |  14 +-
src/qemu/qemu_hotplug.c    |   4 +-
src/qemu/qemu_process.c    |  17 +-
8 files changed, 515 insertions(+), 429 deletions(-)



--
Regards,
Praveen K Paladugu




[libvirt PATCH v3 11/13] ch_driver: add numatune callbacks for CH driver

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 273 +
 1 file changed, 273 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 03db6b2bc8..d7008ef011 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
 #include "viruri.h"
 #include "virutil.h"
 #include "viruuid.h"
+#include "virnuma.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -1296,6 +1297,276 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+  virTypedParameterPtr params,
+  int *nparams,
+  unsigned int flags)
+{
+size_t i;
+virDomainObj *vm = NULL;
+virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+virCHDomainObjPrivate *priv;
+g_autofree char *nodeset = NULL;
+int ret = -1;
+virDomainDef *def = NULL;
+bool live = false;
+virBitmap *autoNodeset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (!(vm = virCHDomainObjFromDomain(dom)))
+return -1;
+priv = vm->privateData;
+
+if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live)
+autoNodeset = priv->autoNodeset;
+
+if ((*nparams) == 0) {
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+goto cleanup;
+}
+
+for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+virMemoryParameterPtr param = ¶ms[i];
+
+switch (i) {
+case 0: /* fill numa mode here */
+ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+VIR_TYPED_PARAM_INT, tmpmode) < 0)
+goto cleanup;
+
+break;
+
+case 1: /* fill numa nodeset here */
+nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, 
-1);
+
+if (!nodeset ||
+virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+VIR_TYPED_PARAM_STRING, nodeset) < 0)
+goto cleanup;
+
+nodeset = NULL;
+break;
+
+/* coverity[dead_error_begin] */
+default:
+break;
+/* should not hit here */
+}
+}
+
+if (*nparams > CH_NB_NUMA_PARAM)
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+  virBitmap *nodeset)
+{
+g_autoptr(virCgroup) cgroup_temp = NULL;
+virCHDomainObjPrivate *priv = vm->privateData;
+g_autofree char *nodeset_str = NULL;
+virDomainNumatuneMemMode mode;
+size_t i = 0;
+
+
+if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
+mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("change of nodeset for running domain requires strict 
numa mode"));
+return -1;
+}
+
+if (!virNumaNodesetIsAvailable(nodeset))
+return -1;
+
+/* Ensure the cpuset string is formatted before passing to cgroup */
+if (!(nodeset_str = virBitmapFormat(nodeset)))
+return -1;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (!vcpu->online)
+continue;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+
+return 0;
+}
+
+for (i = 0; i < vm->def->niothreadids; i++) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+   vm->def->iothreadids[i]->iothread_id,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+return -1;
+}
+
+/* set nodeset for root cgroup */
+if (vi

[libvirt PATCH v3 04/13] ch_driver, ch_domain: vcpu info getter callbacks

2021-12-10 Thread Praveen K Paladugu
Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c |  25 +
 src/ch/ch_domain.h |   4 ++
 src/ch/ch_driver.c | 134 +
 3 files changed, 163 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 36333a8a3f..3f34e87e04 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -336,3 +336,28 @@ virCHDomainGetMonitor(virDomainObj *vm)
 {
 return CH_DOMAIN_PRIVATE(vm)->monitor;
 }
+
+pid_t
+virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid)
+{
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, vcpuid);
+
+return CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid;
+}
+
+bool
+virCHDomainHasVcpuPids(virDomainObj *vm)
+{
+size_t i;
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virDomainVcpuDef *vcpu;
+
+for (i = 0; i < maxvcpus; i++) {
+vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid > 0)
+return true;
+}
+
+return false;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index f01c0e5ad0..1ec7643216 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -82,3 +82,7 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob 
job)
 
 void
 virCHDomainObjEndJob(virDomainObj *obj);
+
+int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
+bool virCHDomainHasVcpuPids(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 108644e503..31e9de7f6a 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -942,6 +942,137 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+static int
+chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
+virDomainObj *vm;
+virDomainDef *def;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_GUEST, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+return -1;
+
+if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
+ret = virDomainDefGetVcpusMax(def);
+else
+ret = virDomainDefGetVcpus(def);
+
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainGetMaxVcpus(virDomainPtr dom)
+{
+return chDomainGetVcpusFlags(dom,
+ (VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+static int
+chDomainHelperGetVcpus(virDomainObj *vm,
+   virVcpuInfoPtr info,
+   unsigned long long *cpuwait,
+   int maxinfo, unsigned char *cpumaps, int maplen)
+{
+size_t ncpuinfo = 0;
+size_t i;
+
+if (maxinfo == 0)
+return 0;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (info)
+memset(info, 0, sizeof(*info) * maxinfo);
+
+if (cpumaps)
+memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; 
i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+pid_t vcpupid = virCHDomainGetVcpuPid(vm, i);
+virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
+
+if (!vcpu->online)
+continue;
+
+if (info) {
+vcpuinfo->number = i;
+vcpuinfo->state = VIR_VCPU_RUNNING;
+if (virProcessGetStatInfo(&vcpuinfo->cpuTime,
+  &vcpuinfo->cpu, NULL,
+  vm->pid, vcpupid) < 0) {
+virReportSystemError(errno, "%s",
+  _("cannot get vCPU placement & pCPU 
time"));
+return -1;
+}
+}
+
+if (cpumaps) {
+unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
+g_autoptr(virBitmap) map = NULL;
+
+if (!(map = virProcessGetAffinity(vcpupid)))
+return -1;
+
+virBitmapToDataBuf(map, cpumap, maplen);
+}
+
+if (cpuwait) {
+if (virProcessGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) 
< 0)
+return -1;
+}
+
+ncpuinfo++;
+}
+
+return ncpuinfo;
+}
+
+static int
+chDomainGetVcpus(virDomainPtr dom,
+ virVcpuInfoPtr info,
+ int maxinfo, unsigned char *cpumaps, int maplen)
+{
+virDomainObj *vm;
+int ret = -1;
+
+

[libvirt PATCH v3 12/13] ch_process: Setup emulator and iothread settings

2021-12-10 Thread Praveen K Paladugu
using virCHProcessSetupPid

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 60 +++
 src/ch/ch_monitor.h |  2 ++
 src/ch/ch_process.c | 77 -
 3 files changed, 138 insertions(+), 1 deletion(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 4de86f3c03..1709c73181 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -921,3 +921,63 @@ virCHMonitorGetInfo(virCHMonitor *mon, virJSONValue **info)
 {
 return virCHMonitorGet(mon, URL_VM_INFO, info);
 }
+
+/**
+ * virCHMonitorGetIOThreads:
+ * @mon: Pointer to the monitor
+ * @iothreads: Location to return array of IOThreadInfo data
+ *
+ * Retrieve the list of iothreads defined/running for the machine
+ *
+ * Returns count of IOThreadInfo structures on success
+ *-1 on error.
+ */
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads)
+{
+size_t nthreads = 0, niothreads = 0;
+int thd_index;
+virDomainIOThreadInfo **iothreadinfolist = NULL, *iothreadinfo = NULL;
+
+*iothreads = NULL;
+nthreads = virCHMonitorRefreshThreadInfo(mon);
+
+iothreadinfolist = g_new0(virDomainIOThreadInfo*, nthreads);
+
+for (thd_index = 0; thd_index < nthreads; thd_index++) {
+virBitmap *map = NULL;
+if (mon->threads[thd_index].type == virCHThreadTypeIO) {
+iothreadinfo = g_new0(virDomainIOThreadInfo, 1);
+
+iothreadinfo->iothread_id = mon->threads[thd_index].ioInfo.tid;
+
+if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
+goto cleanup;
+
+if (virBitmapToData(map, &(iothreadinfo->cpumap),
+&(iothreadinfo->cpumaplen)) < 0) {
+virBitmapFree(map);
+goto cleanup;
+}
+virBitmapFree(map);
+//Append to iothreadinfolist
+iothreadinfolist[niothreads] = iothreadinfo;
+niothreads++;
+}
+}
+VIR_DELETE_ELEMENT_INPLACE(iothreadinfolist,
+   niothreads, nthreads);
+*iothreads = iothreadinfolist;
+VIR_DEBUG("niothreads = %ld", niothreads);
+return niothreads;
+
+cleanup:
+if (iothreadinfolist) {
+for (thd_index = 0; thd_index < niothreads; thd_index++)
+VIR_FREE(iothreadinfolist[thd_index]);
+VIR_FREE(iothreadinfolist);
+}
+if (iothreadinfo)
+VIR_FREE(iothreadinfo);
+return -1;
+}
diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h
index f8c3fa75e8..98edb0faf9 100644
--- a/src/ch/ch_monitor.h
+++ b/src/ch/ch_monitor.h
@@ -118,3 +118,5 @@ int virCHMonitorGetCPUInfo(virCHMonitor *mon,
size_t maxvcpus);
 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh,
  virCHMonitorThreadInfo **threads);
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads);
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 56c8d4216d..1af89e0d9e 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -41,7 +41,6 @@ VIR_LOG_INIT("ch.ch_process");
 #define START_VM_POSTFIX ": starting up vm\n"
 
 
-
 static virCHMonitor *
 virCHProcessConnectMonitor(virCHDriver *driver,
virDomainObj *vm)
@@ -310,6 +309,74 @@ virCHProcessSetupPid(virDomainObj *vm,
 return ret;
 }
 
+static int
+virCHProcessSetupIOThread(virDomainObj *vm,
+ virDomainIOThreadInfo *iothread)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+return virCHProcessSetupPid(vm, iothread->iothread_id,
+   VIR_CGROUP_THREAD_IOTHREAD,
+   iothread->iothread_id,
+   priv->autoCpuset, // This should be updated 
when CLH supports accepting
+ // iothread settings from input domain 
definition
+   vm->def->cputune.iothread_period,
+   vm->def->cputune.iothread_quota,
+   NULL); // CLH doesn't allow choosing a 
scheduler for iothreads.
+}
+
+static int
+virCHProcessSetupIOThreads(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+virDomainIOThreadInfo **iothreads = NULL;
+size_t i;
+size_t  niothreads;
+
+niothreads = virCHMonitorGetIOThreads(priv->monitor, &iothreads);
+for (i = 0; i < niothreads; i++) {
+VIR_DEBUG("IOThread index = %ld , tid = %d", i, 
iothreads[i]->iothread_id);
+if (virCHProcessSetupIOThread(vm, iothreads[i]) < 0)
+return -1;
+}
+return 0;
+}
+
+
+static int
+virCHProcessSetupEmulatorThr

[libvirt PATCH v3 08/13] ch: methods for cgroup mgmt in ch driver

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c|   2 +
 src/ch/ch_conf.h|   4 +-
 src/ch/ch_domain.c  |  34 +
 src/ch/ch_domain.h  |   3 +-
 src/ch/ch_monitor.c |  96 ++
 src/ch/ch_monitor.h |  54 +++-
 src/ch/ch_process.c | 304 ++--
 src/ch/ch_process.h |   3 +
 8 files changed, 483 insertions(+), 17 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index ef6f4b5ba8..cfc1174354 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -129,6 +129,8 @@ virCHDriverConfigNew(bool privileged)
 if (!(cfg = virObjectNew(virCHDriverConfigClass)))
 return NULL;
 
+cfg->cgroupControllers = -1; /* Auto detect */
+
 if (privileged) {
 if (virGetUserID(CH_USER, &cfg->user) < 0)
 return NULL;
diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 8fe69c8545..1790295ede 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -35,11 +35,13 @@ struct _virCHDriverConfig {
 
 char *stateDir;
 char *logDir;
-
+int cgroupControllers;
 uid_t user;
 gid_t group;
 };
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCHDriverConfig, virObjectUnref);
+
 struct _virCHDriver
 {
 virMutex lock;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 3a32ac63d9..42cb4e7dcf 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -324,6 +324,40 @@ chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
_("Serial can only be enabled for a PTY"));
 return -1;
 }
+return 0;
+}
+
+int
+virCHDomainRefreshThreadInfo(virDomainObj *vm)
+{
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virCHMonitorThreadInfo *info = NULL;
+size_t nthreads, ncpus = 0;
+size_t i;
+
+nthreads = virCHMonitorGetThreadInfo(virCHDomainGetMonitor(vm),
+ true, &info);
+
+for (i = 0; i < nthreads; i++) {
+virCHDomainVcpuPrivate *vcpupriv;
+virDomainVcpuDef *vcpu;
+virCHMonitorCPUInfo *vcpuInfo;
+
+if (info[i].type != virCHThreadTypeVcpu)
+continue;
+
+/* TODO: hotplug support */
+vcpuInfo = &info[i].vcpuInfo;
+vcpu = virDomainDefGetVcpu(vm->def, vcpuInfo->cpuid);
+vcpupriv = CH_DOMAIN_VCPU_PRIVATE(vcpu);
+vcpupriv->tid = vcpuInfo->tid;
+ncpus++;
+}
+
+/* TODO: Remove the warning when hotplug is implemented.*/
+if (ncpus != maxvcpus)
+VIR_WARN("Mismatch in the number of cpus, expected: %ld, actual: %ld",
+ maxvcpus, ncpus);
 
 return 0;
 }
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 4fc6251380..7cffe2b4fb 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -89,7 +89,8 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob 
job)
 void
 virCHDomainObjEndJob(virDomainObj *obj);
 
-int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+int virCHDomainRefreshThreadInfo(virDomainObj *vm);
+
 pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
 
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index d48b057814..f4e0f88817 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -41,6 +41,7 @@ VIR_LOG_INIT("ch.ch_monitor");
 
 static virClass *virCHMonitorClass;
 static void virCHMonitorDispose(void *obj);
+static void virCHMonitorThreadInfoFree(virCHMonitor * mon);
 
 static int virCHMonitorOnceInit(void)
 {
@@ -571,6 +572,7 @@ static void virCHMonitorDispose(void *opaque)
 virCHMonitor *mon = opaque;
 
 VIR_DEBUG("mon=%p", mon);
+virCHMonitorThreadInfoFree(mon);
 virObjectUnref(mon->vm);
 }
 
@@ -736,6 +738,100 @@ virCHMonitorGet(virCHMonitor *mon, const char *endpoint, 
virJSONValue **response
 return ret;
 }
 
+static void
+virCHMonitorThreadInfoFree(virCHMonitor *mon)
+{
+mon->nthreads = 0;
+if (mon->threads)
+VIR_FREE(mon->threads);
+}
+
+static size_t
+virCHMonitorRefreshThreadInfo(virCHMonitor *mon)
+{
+virCHMonitorThreadInfo *info = NULL;
+g_autofree pid_t *tids = NULL;
+virDomainObj *vm = mon->vm;
+size_t ntids = 0;
+size_t i;
+
+
+virCHMonitorThreadInfoFree(mon);
+if (virProcessGetPids(vm->pid, &ntids, &tids) < 0) {
+mon->threads = NULL;
+return 0;
+}
+
+info = g_new0(virCHMonitorThreadInfo, ntids);
+for (i = 0; i < ntids; i++) {
+g_autofree char *proc = NULL;
+g_autofree char *data = NULL;
+
+proc = g_strdup_printf("/proc/%d/task/%d/comm",
+   (int)vm->pid, (int)tids[i]);
+
+if (virFileReadAll(proc, (1 << 16), &data) < 0) {
+continue;
+}
+
+VIR_DEBUG("VM PID: %d, TID %d, COMM: %s",
+  (int)v

[libvirt PATCH v3 07/13] qemu, hypervisor: refactor some cgroup mgmt methods

2021-12-10 Thread Praveen K Paladugu
Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared with ch driver for cgroup management.

Signed-off-by: Praveen K Paladugu 
---
 src/hypervisor/domain_cgroup.c | 426 -
 src/hypervisor/domain_cgroup.h |  52 
 src/libvirt_private.syms   |  13 +
 src/qemu/qemu_cgroup.c | 410 +--
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  20 +-
 8 files changed, 522 insertions(+), 431 deletions(-)

diff --git a/src/hypervisor/domain_cgroup.c b/src/hypervisor/domain_cgroup.c
index 61b54f071c..0a1b3867b1 100644
--- a/src/hypervisor/domain_cgroup.c
+++ b/src/hypervisor/domain_cgroup.c
@@ -22,11 +22,12 @@
 
 #include "domain_cgroup.h"
 #include "domain_driver.h"
-
+#include "util/virnuma.h"
+#include "virlog.h"
 #include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
-
+VIR_LOG_INIT("domain.cgroup");
 
 int
 virDomainCgroupSetupBlkio(virCgroup *cgroup, virDomainBlkiotune blkio)
@@ -269,3 +270,424 @@ virDomainCgroupSetMemoryLimitParameters(virCgroup *cgroup,
 
 return 0;
 }
+
+
+int
+virSetupBlkioCgroup(virDomainObj *vm, virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
+if (vm->def->blkio.weight || vm->def->blkio.ndevices) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Block I/O tuning is not available on this 
host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupBlkio(cgroup, vm->def->blkio);
+}
+
+
+int
+virSetupMemoryCgroup(virDomainObj *vm, virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
+if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Memory cgroup is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupMemtune(cgroup, vm->def->mem);
+}
+
+
+int
+virSetupCpusetCgroup(virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
+return 0;
+
+if (virCgroupSetCpusetMemoryMigrate(cgroup, true) < 0)
+return -1;
+
+return 0;
+}
+
+
+int
+virSetupCpuCgroup(virDomainObj *vm, virCgroup *cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
+if (vm->def->cputune.sharesSpecified) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("CPU tuning is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+if (vm->def->cputune.sharesSpecified) {
+
+if (virCgroupSetCpuShares(cgroup, vm->def->cputune.shares) < 0)
+return -1;
+
+}
+
+return 0;
+}
+
+
+int
+virInitCgroup(const char *prefix,
+  virDomainObj * vm,
+  size_t nnicindexes, int *nicindexes,
+  virCgroup * cgroup, int cgroupControllers,
+  unsigned int maxThreadsPerProc,
+  bool privileged, char *machineName)
+{
+if (!privileged)
+return 0;
+
+if (!virCgroupAvailable())
+return 0;
+
+virCgroupFree(cgroup);
+cgroup = NULL;
+
+if (!vm->def->resource)
+vm->def->resource = g_new0(virDomainResourceDef, 1);
+
+if (!vm->def->resource->partition)
+vm->def->resource->partition = g_strdup("/machine");
+
+if (!g_path_is_absolute(vm->def->resource->partition)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Resource partition '%s' must start with '/'"),
+   vm->def->resource->partition);
+return -1;
+}
+
+if (virCgroupNewMachine(machineName,
+prefix,
+vm->def->uuid,
+NULL,
+vm->pid,
+false,
+nnicindexes, nicindexes,
+vm->def->resource->partition,
+cgroupControllers,
+maxThreadsPerProc, &cgroup) < 0) {
+if (virCgroupNewIgnoreError())
+return 0;
+
+return -1;
+}
+
+return 0;
+}
+
+
+void
+virRestoreCgro

[libvirt PATCH v3 02/13] ch_domain: add virCHDomainGetMonitor helper method

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 6 ++
 src/ch/ch_domain.h | 5 +
 2 files changed, 11 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index dd4de9e1ea..bf4ce83595 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -290,3 +290,9 @@ virDomainDefParserConfig virCHDriverDomainDefParserConfig = 
{
 .domainPostParseCallback = virCHDomainDefPostParse,
 .deviceValidateCallback = chValidateDomainDeviceDef,
 };
+
+virCHMonitor *
+virCHDomainGetMonitor(virDomainObj *vm)
+{
+return CH_DOMAIN_PRIVATE(vm)->monitor;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 61b34b0467..c053b25c65 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -57,6 +57,11 @@ struct _virCHDomainObjPrivate {
  virChrdevs *chrdevs;
 };
 
+#define CH_DOMAIN_PRIVATE(vm) \
+((virCHDomainObjPrivate*)(vm)->privateData)
+
+virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH v3 00/13] cgroup and thread management in ch driver.

2021-12-10 Thread Praveen K Paladugu
This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

v3:
* addrressed all the formatting comments in v2 patch set
* dropped indentation patches are they do not adhere to libvirt coding style
* fixed build issue in qemu driver that was introduced in v2

Praveen K Paladugu (5):
  util: Helper functions to get process info
  ch_driver,ch_domain: vcpu info getter callbacks
  qemu,hypervisor: refactor some cgroup mgmt methods
  ch_process: Setup emulator and iothread settings
  ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (8):
  ch_domain: add virCHDomainGetMonitor helper method
  ch_domain: add methods to manage private vcpu data
  ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap
  ch_monitor: Get nicindexes in prep for cgroup mgmt
  ch: methods for cgroup mgmt in ch driver
  ch_driver,ch_domain: vcpupin callback in ch driver
  ch_driver: enable typed param string for numatune
  ch_driver: add numatune callbacks for CH driver

 src/ch/ch_conf.c   |   2 +
 src/ch/ch_conf.h   |   6 +-
 src/ch/ch_domain.c | 172 ++-
 src/ch/ch_domain.h |  32 +-
 src/ch/ch_driver.c | 789 +
 src/ch/ch_monitor.c| 341 +++---
 src/ch/ch_monitor.h|  60 ++-
 src/ch/ch_process.c| 385 +++-
 src/ch/ch_process.h|   3 +
 src/ch/meson.build |   1 +
 src/hypervisor/domain_cgroup.c | 426 +-
 src/hypervisor/domain_cgroup.h |  52 +++
 src/libvirt_private.syms   |  15 +
 src/qemu/qemu_cgroup.c | 410 +
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c | 130 +-
 src/qemu/qemu_hotplug.c|   7 +-
 src/qemu/qemu_process.c|  20 +-
 src/util/virprocess.c  | 108 +
 src/util/virprocess.h  |   5 +
 20 files changed, 2357 insertions(+), 618 deletions(-)

-- 
2.27.0




[libvirt PATCH v3 09/13] ch_driver, ch_domain: vcpupin callback in ch driver

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c  |  30 +
 src/ch/ch_domain.h  |   1 +
 src/ch/ch_driver.c  | 145 
 src/ch/ch_monitor.c |   2 +-
 4 files changed, 177 insertions(+), 1 deletion(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 42cb4e7dcf..524aa330e1 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "datatypes.h"
 #include "ch_domain.h"
 #include "domain_driver.h"
 #include "viralloc.h"
@@ -420,3 +421,32 @@ virCHDomainGetMachineName(virDomainObj *vm)
 
 return ret;
 }
+
+/**
+ * virCHDomainObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObj *
+virCHDomainObjFromDomain(virDomainPtr domain)
+{
+virDomainObj *vm;
+virCHDriver *driver = domain->conn->privateData;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+if (!vm) {
+virUUIDFormat(domain->uuid, uuidstr);
+virReportError(VIR_ERR_NO_DOMAIN,
+   _("no domain with matching uuid '%s' (%s)"),
+   uuidstr, domain->name);
+return NULL;
+}
+
+return vm;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 7cffe2b4fb..b4a245df54 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -95,3 +95,4 @@ pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int 
vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
 
 char *virCHDomainGetMachineName(virDomainObj *vm);
+virDomainObj *virCHDomainObjFromDomain(virDomain *domain);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 97fbd76959..0cc08b6c20 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -25,6 +25,7 @@
 #include "ch_driver.h"
 #include "ch_monitor.h"
 #include "ch_process.h"
+#include "domain_cgroup.h"
 #include "datatypes.h"
 #include "driver.h"
 #include "viraccessapicheck.h"
@@ -1123,6 +1124,148 @@ chDomainGetVcpus(virDomainPtr dom,
 return ret;
 }
 
+static int
+chDomainPinVcpuLive(virDomainObj *vm,
+virDomainDef *def,
+int vcpu,
+virCHDriver *driver,
+virCHDriverConfig *cfg,
+virBitmap *cpumap)
+{
+g_autoptr(virBitmap) tmpmap = NULL;
+g_autoptr(virCgroup) cgroup_vcpu = NULL;
+virDomainVcpuDef *vcpuinfo;
+virCHDomainObjPrivate *priv = vm->privateData;
+
+g_autofree char *str = NULL;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("vcpu %d is out of range of live cpu count %d"),
+   vcpu, virDomainDefGetVcpusMax(def));
+return -1;
+}
+
+if (!(tmpmap = virBitmapNewCopy(cpumap)))
+return -1;
+
+if (!(str = virBitmapFormat(cpumap)))
+return -1;
+
+if (vcpuinfo->online) {
+/* Configure the corresponding cpuset cgroup before set affinity. */
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
+   false, &cgroup_vcpu) < 0)
+return -1;
+if (virSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
+return -1;
+}
+
+if (virProcessSetAffinity(virCHDomainGetVcpuPid(vm, vcpu), cpumap, 
false) < 0)
+return -1;
+}
+
+virBitmapFree(vcpuinfo->cpumask);
+vcpuinfo->cpumask = tmpmap;
+tmpmap = NULL;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+return -1;
+
+return 0;
+}
+
+
+static int
+chDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virBitmap *pcpumap = NULL;
+virDomainVcpuDef *vcpuinfo = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN

[libvirt PATCH v3 10/13] ch_driver: enable typed param string for numatune

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Enable support of VIR_DRV_FEATURE_TYPED_PARAM_STRING to enable numatune

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 0cc08b6c20..03db6b2bc8 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -944,6 +944,36 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+/* Which features are supported by this driver? */
+static int
+chConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+return -1;
+
+switch ((virDrvFeature) feature) {
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
+}
+}
+
 static int
 chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
 {
@@ -1279,6 +1309,7 @@ static virHypervisorDriver chHypervisorDriver = {
 .connectListAllDomains = chConnectListAllDomains,   /* 7.5.0 */
 .connectListDomains = chConnectListDomains, /* 7.5.0 */
 .connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
+.connectSupportsFeature = chConnectSupportsFeature, /* 8.0.0 */
 .domainCreateXML = chDomainCreateXML,   /* 7.5.0 */
 .domainCreate = chDomainCreate, /* 7.5.0 */
 .domainCreateWithFlags = chDomainCreateWithFlags,   /* 7.5.0 */
-- 
2.27.0




[libvirt PATCH v3 06/13] ch_monitor: Get nicindexes in prep for cgroup mgmt

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.h|   2 +
 src/ch/ch_domain.c  |  27 ++-
 src/ch/ch_domain.h  |   2 +
 src/ch/ch_driver.c  |   1 +
 src/ch/ch_monitor.c | 185 ++--
 src/ch/ch_monitor.h |  14 +++-
 src/ch/ch_process.c |   6 +-
 src/ch/meson.build  |   1 +
 8 files changed, 179 insertions(+), 59 deletions(-)

diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 37c36d9a09..8fe69c8545 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -44,6 +44,8 @@ struct _virCHDriver
 {
 virMutex lock;
 
+bool privileged;
+
 /* Require lock to get a reference on the object,
  * lockless access thereafter */
 virCaps *caps;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 3f34e87e04..3a32ac63d9 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -21,10 +21,12 @@
 #include 
 
 #include "ch_domain.h"
+#include "domain_driver.h"
 #include "viralloc.h"
 #include "virchrdev.h"
 #include "virlog.h"
 #include "virtime.h"
+#include "virsystemd.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -134,7 +136,7 @@ virCHDomainObjEndJob(virDomainObj *obj)
 }
 
 static void *
-virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
+virCHDomainObjPrivateAlloc(void *opaque)
 {
 virCHDomainObjPrivate *priv;
 
@@ -150,6 +152,7 @@ virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
 g_free(priv);
 return NULL;
 }
+priv->driver = opaque;
 
 return priv;
 }
@@ -361,3 +364,25 @@ virCHDomainHasVcpuPids(virDomainObj *vm)
 
 return false;
 }
+
+char *
+virCHDomainGetMachineName(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = CH_DOMAIN_PRIVATE(vm);
+virCHDriver *driver = priv->driver;
+char *ret = NULL;
+
+if (vm->pid > 0) {
+ret = virSystemdGetMachineNameByPID(vm->pid);
+if (!ret)
+virResetLastError();
+}
+
+if (!ret)
+ret = virDomainDriverGenerateMachineName("ch",
+ NULL,
+ vm->def->id, vm->def->name,
+ driver->privileged);
+
+return ret;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index c36405808b..4fc6251380 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -92,3 +92,5 @@ virCHDomainObjEndJob(virDomainObj *obj);
 int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
 pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
+
+char *virCHDomainGetMachineName(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index ad7383e96e..97fbd76959 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -934,6 +934,7 @@ static int chStateInitialize(bool privileged,
 goto cleanup;
 }
 
+ch_driver->privileged = privileged;
 ret = VIR_DRV_STATE_INIT_COMPLETE;
 
  cleanup:
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 12c10da874..d48b057814 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -226,7 +226,8 @@ virCHMonitorBuildDisksJson(virJSONValue *content, 
virDomainDef *vmdef)
 }
 
 static int
-virCHMonitorBuildNetJson(virJSONValue *nets, virDomainNetDef *netdef)
+virCHMonitorBuildNetJson(virJSONValue *nets, virDomainNetDef *netdef,
+ size_t *nnicindexes, int **nicindexes)
 {
 virDomainNetType netType = virDomainNetGetActualType(netdef);
 char macaddr[VIR_MAC_STRING_BUFLEN];
@@ -236,59 +237,72 @@ virCHMonitorBuildNetJson(virJSONValue *nets, 
virDomainNetDef *netdef)
 net = virJSONValueNewObject();
 
 switch (netType) {
-case VIR_DOMAIN_NET_TYPE_ETHERNET:
-if (netdef->guestIP.nips == 1) {
-const virNetDevIPAddr *ip = netdef->guestIP.ips[0];
-g_autofree char *addr = NULL;
-virSocketAddr netmask;
-g_autofree char *netmaskStr = NULL;
-if (!(addr = virSocketAddrFormat(&ip->address)))
-return -1;
-if (virJSONValueObjectAppendString(net, "ip", addr) < 0)
-return -1;
+case VIR_DOMAIN_NET_TYPE_ETHERNET:
+if (netdef->guestIP.nips == 1) {
+const virNetDevIPAddr *ip = netdef->guestIP.ips[0];
+g_autofree char *addr = NULL;
+virSocketAddr netmask;
+g_autofree char *netmaskStr = NULL;
+
+if (!(addr = virSocketAddrFormat(&ip->address)))
+return -1;
+if (virJSONValueObjectAppendString(net, "ip", addr) < 0)
+return -1;
+
+if (virSocketAddrPrefixToNetmask(ip->prefix, &netmask, 
AF_INET) < 0) {
+  

[libvirt PATCH v3 01/13] util: Helper functions to get process info

2021-12-10 Thread Praveen K Paladugu
Move qemuGetProcessInfo and qemuGetSchedInfo methods to util and share them
with ch driver.

Signed-off-by: Praveen K Paladugu 
---
 src/libvirt_private.syms |   2 +
 src/qemu/qemu_driver.c   | 116 ++-
 src/util/virprocess.c| 108 
 src/util/virprocess.h|   5 ++
 4 files changed, 120 insertions(+), 111 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index da27ee7b53..56adc192cd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3101,8 +3101,10 @@ virProcessGetAffinity;
 virProcessGetMaxMemLock;
 virProcessGetNamespaces;
 virProcessGetPids;
+virProcessGetSchedInfo;
 virProcessGetStartTime;
 virProcessGetStat;
+virProcessGetStatInfo;
 virProcessGroupGet;
 virProcessGroupKill;
 virProcessKill;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e444ad2d45..ba3efef42b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1317,113 +1317,6 @@ qemuGetSchedstatDelay(unsigned long long *cpudelay,
 return 0;
 }
 
-
-static int
-qemuGetSchedInfo(unsigned long long *cpuWait,
- pid_t pid, pid_t tid)
-{
-g_autofree char *proc = NULL;
-g_autofree char *data = NULL;
-g_auto(GStrv) lines = NULL;
-size_t i;
-double val;
-
-*cpuWait = 0;
-
-/* In general, we cannot assume pid_t fits in int; but /proc parsing
- * is specific to Linux where int works fine.  */
-if (tid)
-proc = g_strdup_printf("/proc/%d/task/%d/sched", (int)pid, (int)tid);
-else
-proc = g_strdup_printf("/proc/%d/sched", (int)pid);
-if (!proc)
-return -1;
-
-/* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
-if (access(proc, R_OK) < 0) {
-return 0;
-}
-
-if (virFileReadAll(proc, (1<<16), &data) < 0)
-return -1;
-
-lines = g_strsplit(data, "\n", 0);
-if (!lines)
-return -1;
-
-for (i = 0; lines[i] != NULL; i++) {
-const char *line = lines[i];
-
-/* Needs CONFIG_SCHEDSTATS. The second check
- * is the old name the kernel used in past */
-if (STRPREFIX(line, "se.statistics.wait_sum") ||
-STRPREFIX(line, "se.wait_sum")) {
-line = strchr(line, ':');
-if (!line) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing separator in sched info '%s'"),
-   lines[i]);
-return -1;
-}
-line++;
-while (*line == ' ')
-line++;
-
-if (virStrToDouble(line, NULL, &val) < 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Unable to parse sched info value '%s'"),
-   line);
-return -1;
-}
-
-*cpuWait = (unsigned long long)(val * 100);
-break;
-}
-}
-
-return 0;
-}
-
-
-static int
-qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
-   pid_t pid, pid_t tid)
-{
-g_auto(GStrv) proc_stat = virProcessGetStat(pid, tid);
-unsigned long long usertime = 0, systime = 0;
-long rss = 0;
-int cpu = 0;
-
-if (!proc_stat ||
-virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_UTIME], NULL, 10, 
&usertime) < 0 ||
-virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_STIME], NULL, 10, 
&systime) < 0 ||
-virStrToLong_l(proc_stat[VIR_PROCESS_STAT_RSS], NULL, 10, &rss) < 0 ||
-virStrToLong_i(proc_stat[VIR_PROCESS_STAT_PROCESSOR], NULL, 10, &cpu) 
< 0) {
-VIR_WARN("cannot parse process status data");
-}
-
-/* We got jiffies
- * We want nanoseconds
- * _SC_CLK_TCK is jiffies per second
- * So calculate thus
- */
-if (cpuTime)
-*cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
-/ (unsigned long long)sysconf(_SC_CLK_TCK);
-if (lastCpu)
-*lastCpu = cpu;
-
-if (vm_rss)
-*vm_rss = rss * virGetSystemPageSizeKB();
-
-
-VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
-  (int)pid, tid, usertime, systime, cpu, rss);
-
-return 0;
-}
-
-
 static int
 qemuDomainHelperGetVcpus(virDomainObj *vm,
  virVcpuInfoPtr info,
@@ -1463,7 +1356,7 @@ qemuDomainHelperGetVcpus(virDomainObj *vm,
 vcpuinfo->number = i;
 vcpuinfo->state = VIR_VCPU_RUNNING;
 
-if (qemuGetProcessInfo(&vcpuinfo->cpuTime,
+if (virProcessGetStatInfo(&vcpuinfo->cpuTime,
&vcpuinfo->cpu, NULL,
vm->pid, vcpupid) < 0) {
  

[libvirt PATCH v3 03/13] ch_domain: add methods to manage private vcpu data

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 50 +-
 src/ch/ch_domain.h | 11 ++
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index bf4ce83595..36333a8a3f 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -164,11 +164,6 @@ virCHDomainObjPrivateFree(void *data)
 g_free(priv);
 }
 
-virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
-.alloc = virCHDomainObjPrivateAlloc,
-.free = virCHDomainObjPrivateFree,
-};
-
 static int
 virCHDomainDefPostParseBasic(virDomainDef *def,
  void *opaque G_GNUC_UNUSED)
@@ -185,6 +180,45 @@ virCHDomainDefPostParseBasic(virDomainDef *def,
 return 0;
 }
 
+static virClass *virCHDomainVcpuPrivateClass;
+static void virCHDomainVcpuPrivateDispose(void *obj);
+
+static int
+virCHDomainVcpuPrivateOnceInit(void)
+{
+if (!VIR_CLASS_NEW(virCHDomainVcpuPrivate, virClassForObject()))
+return -1;
+
+return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virCHDomainVcpuPrivate);
+
+static virObject *
+virCHDomainVcpuPrivateNew(void)
+{
+virCHDomainVcpuPrivate *priv;
+
+if (virCHDomainVcpuPrivateInitialize() < 0)
+return NULL;
+
+if (!(priv = virObjectNew(virCHDomainVcpuPrivateClass)))
+return NULL;
+
+return (virObject *) priv;
+}
+
+
+static void
+virCHDomainVcpuPrivateDispose(void *obj)
+{
+virCHDomainVcpuPrivate *priv = obj;
+
+priv->tid = 0;
+
+return;
+}
+
 static int
 virCHDomainDefPostParse(virDomainDef *def,
 unsigned int parseFlags G_GNUC_UNUSED,
@@ -203,6 +237,12 @@ virCHDomainDefPostParse(virDomainDef *def,
 return 0;
 }
 
+virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
+.alloc = virCHDomainObjPrivateAlloc,
+.free = virCHDomainObjPrivateFree,
+.vcpuNew = virCHDomainVcpuPrivateNew,
+};
+
 static int
 chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
   const virDomainDef *def G_GNUC_UNUSED,
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index c053b25c65..f01c0e5ad0 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -62,6 +62,17 @@ struct _virCHDomainObjPrivate {
 
 virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
 
+typedef struct _virCHDomainVcpuPrivate virCHDomainVcpuPrivate;
+struct _virCHDomainVcpuPrivate {
+virObject parent;
+
+pid_t tid; /* vcpu thread id */
+virTristateBool halted;
+};
+
+#define CH_DOMAIN_VCPU_PRIVATE(vcpu) \
+((virCHDomainVcpuPrivate *) (vcpu)->privateData)
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH v3 13/13] ch_driver: emulator threadinfo & pinning callbacks

2021-12-10 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 154 +
 1 file changed, 154 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index d7008ef011..1f40f6561a 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -1297,6 +1297,158 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+
+
+static int
+chDomainGetEmulatorPinInfo(virDomainPtr dom,
+ unsigned char *cpumaps,
+ int maplen,
+ unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virCHDomainObjPrivate *priv;
+bool live;
+int ret = -1;
+virBitmap *cpumask = NULL;
+g_autoptr(virBitmap) bitmap = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live) {
+priv = vm->privateData;
+autoCpuset = priv->autoCpuset;
+}
+if (def->cputune.emulatorpin) {
+cpumask = def->cputune.emulatorpin;
+} else if (def->cpumask) {
+cpumask = def->cpumask;
+} else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+   autoCpuset) {
+cpumask = autoCpuset;
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+cpumask = bitmap;
+}
+
+virBitmapToDataBuf(cpumask, cpumaps, maplen);
+
+ret = 1;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainPinEmulator(virDomainPtr dom,
+  unsigned char *cpumap,
+  int maplen,
+  unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virCgroup *cgroup_emulator = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virCHDomainObjPrivate *priv;
+virBitmap *pcpumap = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+g_autofree char *str = NULL;
+virTypedParameterPtr eventParams = NULL;
+int eventNparams = 0;
+int eventMaxparams = 0;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+cfg = virCHDriverGetConfig(driver);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto endjob;
+
+priv = vm->privateData;
+
+if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
+goto endjob;
+
+if (virBitmapIsAllClear(pcpumap)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty cpu list for pinning"));
+goto endjob;
+}
+
+if (def) {
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
+   0, false, &cgroup_emulator) < 0)
+goto endjob;
+
+if (virSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+goto endjob;
+}
+}
+
+if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
+goto endjob;
+
+virBitmapFree(def->cputune.emulatorpin);
+def->cputune.emulatorpin = NULL;
+
+if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
+goto endjob;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto endjob;
+
+str = virBitmapFormat(pcpumap);
+if (virTypedParamsAddString(&eventParams, &eventNparams,
+&eventMaxparams,
+VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
+str) < 0)
+goto endjob;
+
+}
+
+
+ret = 0;
+
+endjob:
+virCHDomainObjEndJob(vm);
+
+cleanup:
+if (cgroup_emulator)
+virCgroupFree(cgroup_emulator);
+virBitmapFree(pcpumap);
+virDomainObjEndAPI(&vm);
+return ret

[libvirt PATCH v3 05/13] ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap

2021-12-10 Thread Praveen K Paladugu
From: Vineeth Pillai 

Add domainGetVcpuPinInfo and nodeGetCPUMap callbacks to ch driver

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.h | 10 +++--
 src/ch/ch_driver.c | 51 ++
 2 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 1ec7643216..c36405808b 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -23,6 +23,7 @@
 #include "ch_conf.h"
 #include "ch_monitor.h"
 #include "virchrdev.h"
+#include "vircgroup.h"
 
 /* Give up waiting for mutex after 30 seconds */
 #define CH_JOB_WAIT_TIME (1000ull * 30)
@@ -52,9 +53,14 @@ typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate;
 struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
+virChrdevs *chrdevs;
+virCgroup *cgroup;
+virCHDriver *driver;
 virCHMonitor *monitor;
-
- virChrdevs *chrdevs;
+char *machineName;
+virBitmap *autoNodeset;
+virBitmap *autoCpuset;
+virChrdevs *devs;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 31e9de7f6a..ad7383e96e 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -981,6 +981,55 @@ chDomainGetMaxVcpus(virDomainPtr dom)
   VIR_DOMAIN_VCPU_MAXIMUM));
 }
 
+static int
+chDomainGetVcpuPinInfo(virDomain *dom,
+   int ncpumaps,
+   unsigned char *cpumaps, int maplen, unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+bool live;
+int ret = -1;
+
+g_autoptr(virBitmap) hostcpus = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (!(hostcpus = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+
+if (live)
+autoCpuset = CH_DOMAIN_PRIVATE(vm)->autoCpuset;
+
+ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
+   hostcpus, autoCpuset);
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chNodeGetCPUMap(virConnectPtr conn,
+unsigned char **cpumap,
+unsigned int *online, unsigned int flags)
+{
+if (virNodeGetCPUMapEnsureACL(conn) < 0)
+return -1;
+
+return virHostCPUGetMap(cpumap, online, flags);
+}
+
+
 static int
 chDomainHelperGetVcpus(virDomainObj *vm,
virVcpuInfoPtr info,
@@ -1112,6 +1161,8 @@ static virHypervisorDriver chHypervisorDriver = {
 .domainGetVcpus = chDomainGetVcpus, /* 8.0.0 */
 .domainGetVcpusFlags = chDomainGetVcpusFlags,   /* 8.0.0 */
 .domainGetMaxVcpus = chDomainGetMaxVcpus,   /* 8.0.0 */
+.domainGetVcpuPinInfo = chDomainGetVcpuPinInfo, /* 8.0.0 */
+.nodeGetCPUMap = chNodeGetCPUMap,   /* 8.0.0 */
 };
 
 static virConnectDriver chConnectDriver = {
-- 
2.27.0




Re: [libvirt PATCH v2 11/17] qemu, hypervisor: refactor some cgroup mgmt methods

2021-12-03 Thread Praveen K Paladugu




On 12/3/2021 11:38 AM, Ján Tomko wrote:

On a Thursday in 2021, Praveen K Paladugu wrote:

Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared by ch driver for cgroup management.



The QEMU driver fails to compile after this patch - it seems
qemu_process.c needs to include the header with the functions.

To get a build coverage for most of our supported platforms,
you can push into your private fork of the libvirt repo on gitlab.
The pipeline should run automatically.

Jano


Thanks for catching this.
Just realized, I am only building ch driver in local checks. I will fix 
this immediately.



Signed-off-by: Praveen K Paladugu 
---
src/hypervisor/domain_cgroup.c | 426 -
src/hypervisor/domain_cgroup.h |  52 
src/libvirt_private.syms   |  10 +
src/qemu/qemu_cgroup.c | 410 +--
src/qemu/qemu_cgroup.h |  11 -
src/qemu/qemu_driver.c |  14 +-
src/qemu/qemu_hotplug.c    |   4 +-
src/qemu/qemu_process.c    |  17 +-
8 files changed, 515 insertions(+), 429 deletions(-)



--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH v2 01/17] util: fix indentation in virprocess.c

2021-12-03 Thread Praveen K Paladugu




On 12/3/2021 11:25 AM, Ján Tomko wrote:

On a Thursday in 2021, Praveen K Paladugu wrote:

Signed-off-by: Praveen K Paladugu 


Most of these indentation fixes here are against our coding style:
https://libvirt.org/coding-style.html


It is hard to follow all the formatting guidelines manually. So I 
primarily relied on running "indent" to handle all formatting as 
suggested at 
https://libvirt.org/coding-style.html#code-formatting-especially-for-new-code.


Is there a different tool I can manage all formatting with?




---
src/util/virprocess.c | 501 +-
1 file changed, 249 insertions(+), 252 deletions(-)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 7b0ad9c97b..8288e71f67 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -25,36 +25,36 @@
#include 
#include 
#ifndef WIN32
-# include 
+#include 
#endif
#include 


This is intentional spacing to make it obvious which directives
are conditional. It's enforced by cppi(1) which is run as a part
of our tests, if installed.


-static inline int setns(int fd, int nstype)
+static inline int
+setns(int fd, int nstype)
{


This is good and the style we try to use for new code.

@@ -115,15 +118,11 @@ static inline int setns(int fd G_GNUC_UNUSED, 
int nstype G_GNUC_UNUSED)


VIR_ENUM_IMPL(virProcessSchedPolicy,
  VIR_PROC_POLICY_LAST,
-  "none",
-  "batch",
-  "idle",
-  "fifo",
-  "rr",
-);
+  "none", "batch", "idle", "fifo", "rr",);


One line per enum value makes for nicer diffs




#ifndef WIN32
+
/**
 * virProcessTranslateStatus:
 * @status: child exit status to translate
@@ -136,12 +135,11 @@ char *
virProcessTranslateStatus(int status)
{
    char *buf;
+
    if (WIFEXITED(status)) {
-    buf = g_strdup_printf(_("exit status %d"),
-  WEXITSTATUS(status));
+    buf = g_strdup_printf(_("exit status %d"), WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
-    buf = g_strdup_printf(_("fatal signal %d"),
-  WTERMSIG(status));
+    buf = g_strdup_printf(_("fatal signal %d"), WTERMSIG(status));
    } else {
    buf = g_strdup_printf(_("invalid value %d"), status);
    }
@@ -175,8 +173,7 @@ virProcessAbort(pid_t pid)
 */
    saved_errno = errno;
    VIR_DEBUG("aborting child process %d", pid);
-    while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
-   errno == EINTR);
+    while ((ret = waitpid(pid, &status, WNOHANG)) == -1 && errno == 
EINTR);

    if (ret == pid) {
    tmp = virProcessTranslateStatus(status);
    VIR_DEBUG("process has ended: %s", tmp);
@@ -185,8 +182,7 @@ virProcessAbort(pid_t pid)
    VIR_DEBUG("trying SIGTERM to child process %d", pid);
    kill(pid, SIGTERM);
    g_usleep(10 * 1000);
-    while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
-   errno == EINTR);
+    while ((ret = waitpid(pid, &status, WNOHANG)) == -1 && errno 
== EINTR);

    if (ret == pid) {
    tmp = virProcessTranslateStatus(status);
    VIR_DEBUG("process has ended: %s", tmp);
@@ -194,8 +190,7 @@ virProcessAbort(pid_t pid)
    } else if (ret == 0) {
    VIR_DEBUG("trying SIGKILL to child process %d", pid);
    kill(pid, SIGKILL);
-    while ((ret = waitpid(pid, &status, 0)) == -1 &&
-   errno == EINTR);
+    while ((ret = waitpid(pid, &status, 0)) == -1 && errno == 
EINTR);

    if (ret == pid) {
    tmp = virProcessTranslateStatus(status);
    VIR_DEBUG("process has ended: %s", tmp);
@@ -246,8 +241,7 @@ virProcessWait(pid_t pid, int *exitstatus, bool raw)
    }

    /* Wait for intermediate process to exit */
-    while ((ret = waitpid(pid, &status, 0)) == -1 &&
-   errno == EINTR);
+    while ((ret = waitpid(pid, &status, 0)) == -1 && errno == EINTR);

    if (ret == -1) {
    virReportSystemError(errno, _("unable to wait for process %lld"),
@@ -289,7 +283,7 @@ void
virProcessAbort(pid_t pid)
{
    /* Not yet ported to mingw.  Any volunteers?  */
-    VIR_DEBUG("failed to reap child %lld, abandoning it", (long 
long)pid);
+    VIR_DEBUG("failed to reap child %lld, abandoning it", (long long) 
pid);

}


@@ -305,7 +299,8 @@ virProcessWait(pid_t pid, int *exitstatus 
G_GNUC_UNUSED, bool raw G_GNUC_UNUSED)



/* send signal to a single process */
-int virProcessKill(pid_t pid, int sig)
+int
+virProcessKill(pid_t pid, int sig)
{
    if (pid <= 1) {
    errno = ESRCH;
@@ -315,44 +310,45 @@ int vir

[libvirt PATCH v2 11/17] qemu, hypervisor: refactor some cgroup mgmt methods

2021-12-02 Thread Praveen K Paladugu
Refactor some cgroup management methods from qemu into hypervisor.
These methods will be shared by ch driver for cgroup management.

Signed-off-by: Praveen K Paladugu 
---
 src/hypervisor/domain_cgroup.c | 426 -
 src/hypervisor/domain_cgroup.h |  52 
 src/libvirt_private.syms   |  10 +
 src/qemu/qemu_cgroup.c | 410 +--
 src/qemu/qemu_cgroup.h |  11 -
 src/qemu/qemu_driver.c |  14 +-
 src/qemu/qemu_hotplug.c|   4 +-
 src/qemu/qemu_process.c|  17 +-
 8 files changed, 515 insertions(+), 429 deletions(-)

diff --git a/src/hypervisor/domain_cgroup.c b/src/hypervisor/domain_cgroup.c
index 61b54f071c..eda46e3421 100644
--- a/src/hypervisor/domain_cgroup.c
+++ b/src/hypervisor/domain_cgroup.c
@@ -22,11 +22,12 @@
 
 #include "domain_cgroup.h"
 #include "domain_driver.h"
-
+#include "util/virnuma.h"
+#include "virlog.h"
 #include "virutil.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
-
+VIR_LOG_INIT("domain.cgroup");
 
 int
 virDomainCgroupSetupBlkio(virCgroup *cgroup, virDomainBlkiotune blkio)
@@ -269,3 +270,424 @@ virDomainCgroupSetMemoryLimitParameters(virCgroup *cgroup,
 
 return 0;
 }
+
+
+int
+virSetupBlkioCgroup(virDomainObj * vm, virCgroup * cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
+if (vm->def->blkio.weight || vm->def->blkio.ndevices) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Block I/O tuning is not available on this 
host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupBlkio(cgroup, vm->def->blkio);
+}
+
+
+int
+virSetupMemoryCgroup(virDomainObj * vm, virCgroup * cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
+if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Memory cgroup is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupMemtune(cgroup, vm->def->mem);
+}
+
+
+int
+virSetupCpusetCgroup(virCgroup * cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
+return 0;
+
+if (virCgroupSetCpusetMemoryMigrate(cgroup, true) < 0)
+return -1;
+
+return 0;
+}
+
+
+int
+virSetupCpuCgroup(virDomainObj * vm, virCgroup * cgroup)
+{
+
+if (!virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
+if (vm->def->cputune.sharesSpecified) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("CPU tuning is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+if (vm->def->cputune.sharesSpecified) {
+
+if (virCgroupSetCpuShares(cgroup, vm->def->cputune.shares) < 0)
+return -1;
+
+}
+
+return 0;
+}
+
+
+int
+virInitCgroup(const char *prefix,
+  virDomainObj * vm,
+  size_t nnicindexes, int *nicindexes,
+  virCgroup * cgroup, int cgroupControllers,
+  unsigned int maxThreadsPerProc,
+  bool privileged, char *machineName)
+{
+if (!privileged)
+return 0;
+
+if (!virCgroupAvailable())
+return 0;
+
+virCgroupFree(cgroup);
+cgroup = NULL;
+
+if (!vm->def->resource)
+vm->def->resource = g_new0(virDomainResourceDef, 1);
+
+if (!vm->def->resource->partition)
+vm->def->resource->partition = g_strdup("/machine");
+
+if (!g_path_is_absolute(vm->def->resource->partition)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("Resource partition '%s' must start with '/'"),
+   vm->def->resource->partition);
+return -1;
+}
+
+if (virCgroupNewMachine(machineName,
+prefix,
+vm->def->uuid,
+NULL,
+vm->pid,
+false,
+nnicindexes, nicindexes,
+vm->def->resource->partition,
+cgroupControllers,
+maxThreadsPerProc, &cgroup) < 0) {
+if (virCgroupNewIgnoreError())
+return 0;
+
+return -1;
+}
+
+return 0;
+}
+
+
+void
+virRestoreCgroup

[libvirt PATCH v2 17/17] ch_driver: emulator threadinfo & pinning callbacks

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 154 +
 1 file changed, 154 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 8c14829d2a..100c54163e 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -1309,6 +1309,158 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+
+
+static int
+chDomainGetEmulatorPinInfo(virDomainPtr dom,
+ unsigned char *cpumaps,
+ int maplen,
+ unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virCHDomainObjPrivate *priv;
+bool live;
+int ret = -1;
+virBitmap *cpumask = NULL;
+g_autoptr(virBitmap) bitmap = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live) {
+priv = vm->privateData;
+autoCpuset = priv->autoCpuset;
+}
+if (def->cputune.emulatorpin) {
+cpumask = def->cputune.emulatorpin;
+} else if (def->cpumask) {
+cpumask = def->cpumask;
+} else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+   autoCpuset) {
+cpumask = autoCpuset;
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+cpumask = bitmap;
+}
+
+virBitmapToDataBuf(cpumask, cpumaps, maplen);
+
+ret = 1;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainPinEmulator(virDomainPtr dom,
+  unsigned char *cpumap,
+  int maplen,
+  unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virCgroup *cgroup_emulator = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virCHDomainObjPrivate *priv;
+virBitmap *pcpumap = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+g_autofree char *str = NULL;
+virTypedParameterPtr eventParams = NULL;
+int eventNparams = 0;
+int eventMaxparams = 0;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+cfg = virCHDriverGetConfig(driver);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto endjob;
+
+priv = vm->privateData;
+
+if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
+goto endjob;
+
+if (virBitmapIsAllClear(pcpumap)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty cpu list for pinning"));
+goto endjob;
+}
+
+if (def) {
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
+   0, false, &cgroup_emulator) < 0)
+goto endjob;
+
+if (virSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+goto endjob;
+}
+}
+
+if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
+goto endjob;
+
+virBitmapFree(def->cputune.emulatorpin);
+def->cputune.emulatorpin = NULL;
+
+if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
+goto endjob;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto endjob;
+
+str = virBitmapFormat(pcpumap);
+if (virTypedParamsAddString(&eventParams, &eventNparams,
+&eventMaxparams,
+VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
+str) < 0)
+goto endjob;
+
+}
+
+
+ret = 0;
+
+endjob:
+virCHDomainObjEndJob(vm);
+
+cleanup:
+if (cgroup_emulator)
+virCgroupFree(cgroup_emulator);
+virBitmapFree(pcpumap);
+virDomainObjEndAPI(&vm);
+return ret;

[libvirt PATCH v2 04/17] ch_domain: add virCHDomainGetMonitor helper method

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 6 ++
 src/ch/ch_domain.h | 5 +
 2 files changed, 11 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 44f7d26ca4..7bfe950822 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -288,3 +288,9 @@ virDomainDefParserConfig virCHDriverDomainDefParserConfig = 
{
 .domainPostParseCallback = virCHDomainDefPostParse,
 .deviceValidateCallback = chValidateDomainDeviceDef,
 };
+
+virCHMonitor *
+virCHDomainGetMonitor(virDomainObj * vm)
+{
+return CH_DOMAIN_PRIVATE(vm)->monitor;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 61b34b0467..04d19398b4 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -57,6 +57,11 @@ struct _virCHDomainObjPrivate {
  virChrdevs *chrdevs;
 };
 
+#define CH_DOMAIN_PRIVATE(vm) \
+((virCHDomainObjPrivate *) (vm)->privateData)
+
+virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH v2 16/17] ch_process: Setup emulator and iothread settings

2021-12-02 Thread Praveen K Paladugu
using virCHProcessSetupPid

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 60 ++
 src/ch/ch_monitor.h |  2 ++
 src/ch/ch_process.c | 78 +++--
 3 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index d7593d4aa6..308487b4ff 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -941,3 +941,63 @@ virCHMonitorGetInfo(virCHMonitor * mon, virJSONValue ** 
info)
 {
 return virCHMonitorGet(mon, URL_VM_INFO, info);
 }
+
+/**
+ * virCHMonitorGetIOThreads:
+ * @mon: Pointer to the monitor
+ * @iothreads: Location to return array of IOThreadInfo data
+ *
+ * Retrieve the list of iothreads defined/running for the machine
+ *
+ * Returns count of IOThreadInfo structures on success
+ *-1 on error.
+ */
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads)
+{
+size_t nthreads = 0, niothreads = 0;
+int thd_index;
+virDomainIOThreadInfo **iothreadinfolist = NULL, *iothreadinfo = NULL;
+
+*iothreads = NULL;
+nthreads = virCHMonitorRefreshThreadInfo(mon);
+
+iothreadinfolist = g_new0(virDomainIOThreadInfo*, nthreads);
+
+for (thd_index = 0; thd_index < nthreads; thd_index++) {
+virBitmap *map = NULL;
+if (mon->threads[thd_index].type == virCHThreadTypeIO) {
+iothreadinfo = g_new0(virDomainIOThreadInfo, 1);
+
+iothreadinfo->iothread_id = mon->threads[thd_index].ioInfo.tid;
+
+if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
+goto cleanup;
+
+if (virBitmapToData(map, &(iothreadinfo->cpumap),
+&(iothreadinfo->cpumaplen)) < 0) {
+virBitmapFree(map);
+goto cleanup;
+}
+virBitmapFree(map);
+//Append to iothreadinfolist
+iothreadinfolist[niothreads] = iothreadinfo;
+niothreads++;
+}
+}
+VIR_DELETE_ELEMENT_INPLACE(iothreadinfolist,
+   niothreads, nthreads);
+*iothreads = iothreadinfolist;
+VIR_DEBUG("niothreads = %ld", niothreads);
+return niothreads;
+
+cleanup:
+if (iothreadinfolist) {
+for (thd_index = 0; thd_index < niothreads; thd_index++)
+VIR_FREE(iothreadinfolist[thd_index]);
+VIR_FREE(iothreadinfolist);
+}
+if (iothreadinfo)
+VIR_FREE(iothreadinfo);
+return -1;
+}
diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h
index f8c3fa75e8..98edb0faf9 100644
--- a/src/ch/ch_monitor.h
+++ b/src/ch/ch_monitor.h
@@ -118,3 +118,5 @@ int virCHMonitorGetCPUInfo(virCHMonitor *mon,
size_t maxvcpus);
 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh,
  virCHMonitorThreadInfo **threads);
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads);
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 7a51531224..1c0f5d0818 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -41,7 +41,6 @@ VIR_LOG_INIT("ch.ch_process");
 #define START_VM_POSTFIX ": starting up vm\n"
 
 
-
 static virCHMonitor *
 virCHProcessConnectMonitor(virCHDriver *driver,
virDomainObj *vm)
@@ -131,7 +130,6 @@ virCHProcessUpdateInfo(virDomainObj *vm)
 virCHProcessUpdateConsole(vm, info);
 
 virJSONValueFree(info);
-
 return 0;
 }
 
@@ -312,6 +310,74 @@ virCHProcessSetupPid(virDomainObj *vm,
 return ret;
 }
 
+static int
+virCHProcessSetupIOThread(virDomainObj *vm,
+ virDomainIOThreadInfo *iothread)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+return virCHProcessSetupPid(vm, iothread->iothread_id,
+   VIR_CGROUP_THREAD_IOTHREAD,
+   iothread->iothread_id,
+   priv->autoCpuset, // This should be updated 
when CLH supports accepting
+ // iothread settings from input domain 
definition
+   vm->def->cputune.iothread_period,
+   vm->def->cputune.iothread_quota,
+   NULL); // CLH doesn't allow choosing a 
scheduler for iothreads.
+}
+
+static int
+virCHProcessSetupIOThreads(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+virDomainIOThreadInfo **iothreads = NULL;
+size_t i;
+size_t  niothreads;
+
+niothreads = virCHMonitorGetIOThreads(priv->monitor, &iothreads);
+for (i = 0; i < niothreads; i++) {
+VIR_DEBUG("IOThread index = %ld , tid = %d", i, 
iothreads[i]->iothread_id);
+ 

[libvirt PATCH v2 06/17] ch_driver: fix indentation in ch_driver

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 241 +++--
 1 file changed, 121 insertions(+), 120 deletions(-)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 464bcef907..75c6a15dd6 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -50,7 +50,7 @@ VIR_LOG_INIT("ch.ch_driver");
 virCHDriver *ch_driver = NULL;
 
 static virDomainObj *
-chDomObjFromDomain(virDomain *domain)
+chDomObjFromDomain(virDomain * domain)
 {
 virDomainObj *vm;
 virCHDriver *driver = domain->conn->privateData;
@@ -79,10 +79,10 @@ chConnectURIProbe(char **uri)
 return 1;
 }
 
-static virDrvOpenStatus chConnectOpen(virConnectPtr conn,
-  virConnectAuthPtr auth G_GNUC_UNUSED,
-  virConf *conf G_GNUC_UNUSED,
-  unsigned int flags)
+static virDrvOpenStatus
+chConnectOpen(virConnectPtr conn,
+  virConnectAuthPtr auth G_GNUC_UNUSED,
+  virConf * conf G_GNUC_UNUSED, unsigned int flags)
 {
 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
 
@@ -101,13 +101,15 @@ static virDrvOpenStatus chConnectOpen(virConnectPtr conn,
 return VIR_DRV_OPEN_SUCCESS;
 }
 
-static int chConnectClose(virConnectPtr conn)
+static int
+chConnectClose(virConnectPtr conn)
 {
 conn->privateData = NULL;
 return 0;
 }
 
-static const char *chConnectGetType(virConnectPtr conn)
+static const char *
+chConnectGetType(virConnectPtr conn)
 {
 if (virConnectGetTypeEnsureACL(conn) < 0)
 return NULL;
@@ -115,8 +117,8 @@ static const char *chConnectGetType(virConnectPtr conn)
 return "CH";
 }
 
-static int chConnectGetVersion(virConnectPtr conn,
-   unsigned long *version)
+static int
+chConnectGetVersion(virConnectPtr conn, unsigned long *version)
 {
 virCHDriver *driver = conn->privateData;
 
@@ -129,7 +131,8 @@ static int chConnectGetVersion(virConnectPtr conn,
 return 0;
 }
 
-static char *chConnectGetHostname(virConnectPtr conn)
+static char *
+chConnectGetHostname(virConnectPtr conn)
 {
 if (virConnectGetHostnameEnsureACL(conn) < 0)
 return NULL;
@@ -137,7 +140,8 @@ static char *chConnectGetHostname(virConnectPtr conn)
 return virGetHostname();
 }
 
-static int chConnectNumOfDomains(virConnectPtr conn)
+static int
+chConnectNumOfDomains(virConnectPtr conn)
 {
 virCHDriver *driver = conn->privateData;
 
@@ -148,7 +152,8 @@ static int chConnectNumOfDomains(virConnectPtr conn)
 virConnectNumOfDomainsCheckACL, conn);
 }
 
-static int chConnectListDomains(virConnectPtr conn, int *ids, int nids)
+static int
+chConnectListDomains(virConnectPtr conn, int *ids, int nids)
 {
 virCHDriver *driver = conn->privateData;
 
@@ -156,13 +161,12 @@ static int chConnectListDomains(virConnectPtr conn, int 
*ids, int nids)
 return -1;
 
 return virDomainObjListGetActiveIDs(driver->domains, ids, nids,
- virConnectListDomainsCheckACL, conn);
+virConnectListDomainsCheckACL, conn);
 }
 
 static int
 chConnectListAllDomains(virConnectPtr conn,
-virDomainPtr **domains,
-unsigned int flags)
+virDomainPtr ** domains, unsigned int flags)
 {
 virCHDriver *driver = conn->privateData;
 
@@ -172,11 +176,11 @@ chConnectListAllDomains(virConnectPtr conn,
 return -1;
 
 return virDomainObjListExport(driver->domains, conn, domains,
- virConnectListAllDomainsCheckACL, flags);
+  virConnectListAllDomainsCheckACL, flags);
 }
 
-static int chNodeGetInfo(virConnectPtr conn,
- virNodeInfoPtr nodeinfo)
+static int
+chNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo)
 {
 if (virNodeGetInfoEnsureACL(conn) < 0)
 return -1;
@@ -184,7 +188,8 @@ static int chNodeGetInfo(virConnectPtr conn,
 return virCapabilitiesGetNodeInfo(nodeinfo);
 }
 
-static char *chConnectGetCapabilities(virConnectPtr conn)
+static char *
+chConnectGetCapabilities(virConnectPtr conn)
 {
 virCHDriver *driver = conn->privateData;
 virCaps *caps;
@@ -213,9 +218,7 @@ static char *chConnectGetCapabilities(virConnectPtr conn)
  * Returns a new domain object or NULL in case of failure.
  */
 static virDomainPtr
-chDomainCreateXML(virConnectPtr conn,
-  const char *xml,
-  unsigned int flags)
+chDomainCreateXML(virConnectPtr conn, const char *xml, unsigned int flags)
 {
 virCHDriver *driver = conn->privateData;
 virDomainDef *vmdef = NULL;
@@ -240,8 +243,7 @@ chDomainCreateXML(virConnectPtr conn,
&vmdef,
driver->xml

[libvirt PATCH v2 01/17] util: fix indentation in virprocess.c

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/util/virprocess.c | 501 +-
 1 file changed, 249 insertions(+), 252 deletions(-)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 7b0ad9c97b..8288e71f67 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -25,36 +25,36 @@
 #include 
 #include 
 #ifndef WIN32
-# include 
+#include 
 #endif
 #include 
 #if WITH_SYS_MOUNT_H
-# include 
+#include 
 #endif
 #if WITH_SETRLIMIT
-# include 
-# include 
+#include 
+#include 
 #endif
 #if WITH_SCHED_H
-# include 
+#include 
 #endif
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || 
WITH_BSD_CPU_AFFINITY
-# include 
+#include 
 #endif
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-# include 
-# include 
+#include 
+#include 
 #endif
 
 #if WITH_BSD_CPU_AFFINITY
-# include 
+#include 
 #endif
 
 #ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include 
+#define WIN32_LEAN_AND_MEAN
+#include 
 #endif
 
 #include "virprocess.h"
@@ -71,41 +71,44 @@
 VIR_LOG_INIT("util.process");
 
 #ifdef __linux__
+
 /*
  * Workaround older glibc. While kernel may support the setns
  * syscall, the glibc wrapper might not exist. If that's the
  * case, use our own.
  */
-# ifndef __NR_setns
-#  if defined(__x86_64__)
-#   define __NR_setns 308
-#  elif defined(__i386__)
-#   define __NR_setns 346
-#  elif defined(__arm__)
-#   define __NR_setns 375
-#  elif defined(__aarch64__)
-#   define __NR_setns 375
-#  elif defined(__powerpc__)
-#   define __NR_setns 350
-#  elif defined(__s390__)
-#   define __NR_setns 339
-#  endif
-# endif
-
-# ifndef WITH_SETNS
-#  if defined(__NR_setns)
-#   include 
-
-static inline int setns(int fd, int nstype)
+#ifndef __NR_setns
+#if defined(__x86_64__)
+#define __NR_setns 308
+#elif defined(__i386__)
+#define __NR_setns 346
+#elif defined(__arm__)
+#define __NR_setns 375
+#elif defined(__aarch64__)
+#define __NR_setns 375
+#elif defined(__powerpc__)
+#define __NR_setns 350
+#elif defined(__s390__)
+#define __NR_setns 339
+#endif
+#endif
+
+#ifndef WITH_SETNS
+#if defined(__NR_setns)
+#include 
+
+static inline int
+setns(int fd, int nstype)
 {
 return syscall(__NR_setns, fd, nstype);
 }
-#  else /* !__NR_setns */
-#   error Please determine the syscall number for setns on your architecture
-#  endif
-# endif
+#else /* !__NR_setns */
+#error Please determine the syscall number for setns on your architecture
+#endif
+#endif
 #else /* !__linux__ */
-static inline int setns(int fd G_GNUC_UNUSED, int nstype G_GNUC_UNUSED)
+static inline int
+setns(int fd G_GNUC_UNUSED, int nstype G_GNUC_UNUSED)
 {
 virReportSystemError(ENOSYS, "%s",
  _("Namespaces are not supported on this platform."));
@@ -115,15 +118,11 @@ static inline int setns(int fd G_GNUC_UNUSED, int nstype 
G_GNUC_UNUSED)
 
 VIR_ENUM_IMPL(virProcessSchedPolicy,
   VIR_PROC_POLICY_LAST,
-  "none",
-  "batch",
-  "idle",
-  "fifo",
-  "rr",
-);
+  "none", "batch", "idle", "fifo", "rr",);
 
 
 #ifndef WIN32
+
 /**
  * virProcessTranslateStatus:
  * @status: child exit status to translate
@@ -136,12 +135,11 @@ char *
 virProcessTranslateStatus(int status)
 {
 char *buf;
+
 if (WIFEXITED(status)) {
-buf = g_strdup_printf(_("exit status %d"),
-  WEXITSTATUS(status));
+buf = g_strdup_printf(_("exit status %d"), WEXITSTATUS(status));
 } else if (WIFSIGNALED(status)) {
-buf = g_strdup_printf(_("fatal signal %d"),
-  WTERMSIG(status));
+buf = g_strdup_printf(_("fatal signal %d"), WTERMSIG(status));
 } else {
 buf = g_strdup_printf(_("invalid value %d"), status);
 }
@@ -175,8 +173,7 @@ virProcessAbort(pid_t pid)
  */
 saved_errno = errno;
 VIR_DEBUG("aborting child process %d", pid);
-while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
-   errno == EINTR);
+while ((ret = waitpid(pid, &status, WNOHANG)) == -1 && errno == EINTR);
 if (ret == pid) {
 tmp = virProcessTranslateStatus(status);
 VIR_DEBUG("process has ended: %s", tmp);
@@ -185,8 +182,7 @@ virProcessAbort(pid_t pid)
 VIR_DEBUG("trying SIGTERM to child process %d", pid);
 kill(pid, SIGTERM);
 g_usleep(10 * 1000);
-while ((ret = waitpid(pid, &status, WNOHANG)) == -1 &&
-   errno == EINTR);
+while ((ret = waitpid(pid, &status, WNOHANG)) == -1 && errno == EINTR);
 if (ret == pid) {
 tmp = virProcessTranslateStatus(status);
 VIR_DEBUG("process has ended: %s", tmp);
@@ -194,8 +190,7 @@

[libvirt PATCH v2 12/17] ch: methods for cgroup mgmt in ch driver

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.c|   2 +
 src/ch/ch_conf.h|   4 +-
 src/ch/ch_domain.c  |  34 +
 src/ch/ch_domain.h  |   3 +-
 src/ch/ch_monitor.c |  96 ++
 src/ch/ch_monitor.h |  54 +++-
 src/ch/ch_process.c | 306 ++--
 src/ch/ch_process.h |   3 +
 8 files changed, 484 insertions(+), 18 deletions(-)

diff --git a/src/ch/ch_conf.c b/src/ch/ch_conf.c
index ef6f4b5ba8..cfc1174354 100644
--- a/src/ch/ch_conf.c
+++ b/src/ch/ch_conf.c
@@ -129,6 +129,8 @@ virCHDriverConfigNew(bool privileged)
 if (!(cfg = virObjectNew(virCHDriverConfigClass)))
 return NULL;
 
+cfg->cgroupControllers = -1; /* Auto detect */
+
 if (privileged) {
 if (virGetUserID(CH_USER, &cfg->user) < 0)
 return NULL;
diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 8fe69c8545..1790295ede 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -35,11 +35,13 @@ struct _virCHDriverConfig {
 
 char *stateDir;
 char *logDir;
-
+int cgroupControllers;
 uid_t user;
 gid_t group;
 };
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCHDriverConfig, virObjectUnref);
+
 struct _virCHDriver
 {
 virMutex lock;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 326c3802c3..0a0b1206d6 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -322,6 +322,40 @@ chValidateDomainDeviceDef(const virDomainDeviceDef * dev,
_("Serial can only be enabled for a PTY"));
 return -1;
 }
+return 0;
+}
+
+int
+virCHDomainRefreshThreadInfo(virDomainObj * vm)
+{
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virCHMonitorThreadInfo *info = NULL;
+size_t nthreads, ncpus = 0;
+size_t i;
+
+nthreads = virCHMonitorGetThreadInfo(virCHDomainGetMonitor(vm),
+ true, &info);
+
+for (i = 0; i < nthreads; i++) {
+virCHDomainVcpuPrivate *vcpupriv;
+virDomainVcpuDef *vcpu;
+virCHMonitorCPUInfo *vcpuInfo;
+
+if (info[i].type != virCHThreadTypeVcpu)
+continue;
+
+// TODO: hotplug support
+vcpuInfo = &info[i].vcpuInfo;
+vcpu = virDomainDefGetVcpu(vm->def, vcpuInfo->cpuid);
+vcpupriv = CH_DOMAIN_VCPU_PRIVATE(vcpu);
+vcpupriv->tid = vcpuInfo->tid;
+ncpus++;
+}
+
+// TODO: Remove the warning when hotplug is implemented.
+if (ncpus != maxvcpus)
+VIR_WARN("Mismatch in the number of cpus, expected: %ld, actual: %ld",
+ maxvcpus, ncpus);
 
 return 0;
 }
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 3ac3421015..2ce3e2cef3 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -89,7 +89,8 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob 
job)
 void
 virCHDomainObjEndJob(virDomainObj *obj);
 
-int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+int virCHDomainRefreshThreadInfo(virDomainObj *vm);
+
 pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
 
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 6bc7d035ad..d7593d4aa6 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -41,6 +41,7 @@ VIR_LOG_INIT("ch.ch_monitor");
 
 static virClass *virCHMonitorClass;
 static void virCHMonitorDispose(void *obj);
+static void virCHMonitorThreadInfoFree(virCHMonitor * mon);
 
 static int
 virCHMonitorOnceInit(void)
@@ -589,6 +590,7 @@ virCHMonitorDispose(void *opaque)
 virCHMonitor *mon = opaque;
 
 VIR_DEBUG("mon=%p", mon);
+virCHMonitorThreadInfoFree(mon);
 virObjectUnref(mon->vm);
 }
 
@@ -756,6 +758,100 @@ virCHMonitorGet(virCHMonitor * mon, const char *endpoint,
 return ret;
 }
 
+static void
+virCHMonitorThreadInfoFree(virCHMonitor * mon)
+{
+mon->nthreads = 0;
+if (mon->threads)
+VIR_FREE(mon->threads);
+}
+
+static size_t
+virCHMonitorRefreshThreadInfo(virCHMonitor * mon)
+{
+virCHMonitorThreadInfo *info = NULL;
+g_autofree pid_t *tids = NULL;
+virDomainObj *vm = mon->vm;
+size_t ntids = 0;
+size_t i;
+
+
+virCHMonitorThreadInfoFree(mon);
+if (virProcessGetPids(vm->pid, &ntids, &tids) < 0) {
+mon->threads = NULL;
+return 0;
+}
+
+info = g_new0(virCHMonitorThreadInfo, ntids);
+for (i = 0; i < ntids; i++) {
+g_autofree char *proc = NULL;
+g_autofree char *data = NULL;
+
+proc = g_strdup_printf("/proc/%d/task/%d/comm",
+   (int) vm->pid, (int) tids[i]);
+
+if (virFileReadAll(proc, (1 << 16), &data) < 0) {
+continue;
+}
+
+VIR_DEBUG("VM PID: %d, TID %d, COMM: %s",
+  (int) vm->pid, (int) tids[i], data);

[libvirt PATCH v2 10/17] ch_monitor: Get nicindexes in prep for cgroup mgmt

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.h|  2 ++
 src/ch/ch_domain.c  | 27 +-
 src/ch/ch_domain.h  |  4 +--
 src/ch/ch_driver.c  |  1 +
 src/ch/ch_monitor.c | 86 +
 src/ch/ch_monitor.h | 14 +++-
 src/ch/ch_process.c |  6 +++-
 src/ch/meson.build  |  1 +
 8 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 37c36d9a09..8fe69c8545 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -44,6 +44,8 @@ struct _virCHDriver
 {
 virMutex lock;
 
+bool privileged;
+
 /* Require lock to get a reference on the object,
  * lockless access thereafter */
 virCaps *caps;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index d81221679e..326c3802c3 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -21,10 +21,12 @@
 #include 
 
 #include "ch_domain.h"
+#include "domain_driver.h"
 #include "viralloc.h"
 #include "virchrdev.h"
 #include "virlog.h"
 #include "virtime.h"
+#include "virsystemd.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -129,7 +131,7 @@ virCHDomainObjEndJob(virDomainObj * obj)
 }
 
 static void *
-virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
+virCHDomainObjPrivateAlloc(void *opaque)
 {
 virCHDomainObjPrivate *priv;
 
@@ -145,6 +147,7 @@ virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
 g_free(priv);
 return NULL;
 }
+priv->driver = opaque;
 
 return priv;
 }
@@ -359,3 +362,25 @@ virCHDomainHasVcpuPids(virDomainObj * vm)
 
 return false;
 }
+
+char *
+virCHDomainGetMachineName(virDomainObj * vm)
+{
+virCHDomainObjPrivate *priv = CH_DOMAIN_PRIVATE(vm);
+virCHDriver *driver = priv->driver;
+char *ret = NULL;
+
+if (vm->pid > 0) {
+ret = virSystemdGetMachineNameByPID(vm->pid);
+if (!ret)
+virResetLastError();
+}
+
+if (!ret)
+ret = virDomainDriverGenerateMachineName("ch",
+ NULL,
+ vm->def->id, vm->def->name,
+ driver->privileged);
+
+return ret;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index e35777a9ec..3ac3421015 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -54,9 +54,7 @@ struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
 virChrdevs *chrdevs;
-
 virCgroup *cgroup;
-
 virCHDriver *driver;
 virCHMonitor *monitor;
 char *machineName;
@@ -94,3 +92,5 @@ virCHDomainObjEndJob(virDomainObj *obj);
 int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
 pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
+
+char *virCHDomainGetMachineName(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 86d2776354..39e754d1ff 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -936,6 +936,7 @@ chStateInitialize(bool privileged,
 goto cleanup;
 }
 
+ch_driver->privileged = privileged;
 ret = VIR_DRV_STATE_INIT_COMPLETE;
 
  cleanup:
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 68fa5b30aa..6bc7d035ad 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -236,7 +236,8 @@ virCHMonitorBuildDisksJson(virJSONValue * content, 
virDomainDef * vmdef)
 }
 
 static int
-virCHMonitorBuildNetJson(virJSONValue * nets, virDomainNetDef * netdef)
+virCHMonitorBuildNetJson(virJSONValue * nets, virDomainNetDef * netdef,
+ size_t *nnicindexes, int **nicindexes)
 {
 virDomainNetType netType = virDomainNetGetActualType(netdef);
 char macaddr[VIR_MAC_STRING_BUFLEN];
@@ -275,6 +276,18 @@ virCHMonitorBuildNetJson(virJSONValue * nets, 
virDomainNetDef * netdef)
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("ethernet type supports a single guest ip"));
 }
+/* network and bridge use a tap device, and direct uses a
+ * macvtap device
+ */
+if (nicindexes && nnicindexes && netdef->ifname) {
+int nicindex = 0;
+
+if (virNetDevGetIndex(netdef->ifname, &nicindex) < 0)
+return -1;
+
+VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex);
+}
+
 break;
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
 if ((virDomainChrType) netdef->data.vhostuser->type !=
@@ -354,7 +367,8 @@ virCHMonitorBuildNetJson(virJSONValue * nets, 
virDomainNetDef * netdef)
 }
 
 static int
-virCHMonitorBuildNetsJson(virJSONValue * content, virDomainDef * vmdef)
+virCHMonitorBuildNetsJson(virJSONValue * conte

[libvirt PATCH v2 00/17] cgroup and thread management in ch driver

2021-12-02 Thread Praveen K Paladugu
I addressed all the open comments on the v1 patch set.
In places where indentaion was hard to manage, I created explicit commits to
apply correct indentation on files.

Compared to v1, this version applies 2 code refactors:
1) some cgroup methods in src/qemu/qemu_cgroup.c were moved to src/hypervisor
and shared with ch driver.
2) virProcessGetStatInfo, virProcessGetSchedInfo which were copied from qemu
driver are moved to util and shared between qemu and ch drviers.

Praveen K Paladugu (9):
  util: fix indentation in virprocess.c
  util: Helper functions to get process info
  ch_domain: fix indentation in ch_domain
  ch_driver: fix indentation in ch_driver
  ch_driver,ch_domain: vcpu info getter callbacks
  ch_monitor: fix indentation in ch_monitor.c
  qemu,hypervisor: refactor some cgroup mgmt methods
  ch_process: Setup emulator and iothread settings
  ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (8):
  ch_domain: add virCHDomainGetMonitor helper method
  ch_domain: add methods to manage private vcpu data
  ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap
  ch_monitor: Get nicindexes in prep for cgroup mgmt
  ch: methods for cgroup mgmt in ch driver
  ch_driver,ch_domain: vcpupin callback in ch driver
  ch_driver: enable typed param string for numatune
  ch_driver: add numatune callbacks for CH driver

 src/ch/ch_conf.c   |2 +
 src/ch/ch_conf.h   |6 +-
 src/ch/ch_domain.c |  302 ++---
 src/ch/ch_domain.h |   32 +-
 src/ch/ch_driver.c | 1045 
 src/ch/ch_monitor.c|  533 +++-
 src/ch/ch_monitor.h|   60 +-
 src/ch/ch_process.c|  386 +++-
 src/ch/ch_process.h|3 +
 src/ch/meson.build |1 +
 src/hypervisor/domain_cgroup.c |  426 -
 src/hypervisor/domain_cgroup.h |   52 ++
 src/libvirt_private.syms   |   12 +
 src/qemu/qemu_cgroup.c |  410 +
 src/qemu/qemu_cgroup.h |   11 -
 src/qemu/qemu_driver.c |  130 +---
 src/qemu/qemu_hotplug.c|4 +-
 src/qemu/qemu_process.c|   17 +-
 src/util/virprocess.c  |  609 +++
 src/util/virprocess.h  |5 +
 20 files changed, 2905 insertions(+), 1141 deletions(-)

-- 
2.27.0




[libvirt PATCH v2 13/17] ch_driver, ch_domain: vcpupin callback in ch driver

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c |  30 +
 src/ch/ch_domain.h |   1 +
 src/ch/ch_driver.c | 151 +
 3 files changed, 182 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 0a0b1206d6..de084ca15e 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "datatypes.h"
 #include "ch_domain.h"
 #include "domain_driver.h"
 #include "viralloc.h"
@@ -418,3 +419,32 @@ virCHDomainGetMachineName(virDomainObj * vm)
 
 return ret;
 }
+
+/**
+ * virCHDomainObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObj *
+virCHDomainObjFromDomain(virDomainPtr domain)
+{
+virDomainObj *vm;
+virCHDriver *driver = domain->conn->privateData;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+if (!vm) {
+virUUIDFormat(domain->uuid, uuidstr);
+virReportError(VIR_ERR_NO_DOMAIN,
+   _("no domain with matching uuid '%s' (%s)"),
+   uuidstr, domain->name);
+return NULL;
+}
+
+return vm;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 2ce3e2cef3..db1451405b 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -95,3 +95,4 @@ pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int 
vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
 
 char *virCHDomainGetMachineName(virDomainObj *vm);
+virDomainObj *virCHDomainObjFromDomain(virDomain *domain);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 39e754d1ff..400dfee766 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -25,6 +25,7 @@
 #include "ch_driver.h"
 #include "ch_monitor.h"
 #include "ch_process.h"
+#include "domain_cgroup.h"
 #include "datatypes.h"
 #include "driver.h"
 #include "viraccessapicheck.h"
@@ -1129,6 +1130,154 @@ chDomainGetVcpus(virDomainPtr dom,
 return ret;
 }
 
+static int
+chDomainPinVcpuLive(virDomainObj *vm,
+virDomainDef *def,
+int vcpu,
+virCHDriver *driver,
+virCHDriverConfig *cfg,
+virBitmap *cpumap)
+{
+virBitmap *tmpmap = NULL;
+virDomainVcpuDef *vcpuinfo;
+virCHDomainObjPrivate *priv = vm->privateData;
+virCgroup *cgroup_vcpu = NULL;
+g_autofree char *str = NULL;
+int ret = -1;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+goto cleanup;
+}
+
+if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("vcpu %d is out of range of live cpu count %d"),
+   vcpu, virDomainDefGetVcpusMax(def));
+goto cleanup;
+}
+
+if (!(tmpmap = virBitmapNewCopy(cpumap)))
+goto cleanup;
+
+if (!(str = virBitmapFormat(cpumap)))
+goto cleanup;
+
+if (vcpuinfo->online) {
+/* Configure the corresponding cpuset cgroup before set affinity. */
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
+   false, &cgroup_vcpu) < 0)
+goto cleanup;
+if (virSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
+goto cleanup;
+}
+
+if (virProcessSetAffinity(virCHDomainGetVcpuPid(vm, vcpu), cpumap, 
false) < 0)
+goto cleanup;
+}
+
+virBitmapFree(vcpuinfo->cpumask);
+vcpuinfo->cpumask = tmpmap;
+tmpmap = NULL;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+virBitmapFree(tmpmap);
+virCgroupFree(cgroup_vcpu);
+return ret;
+}
+
+
+static int
+chDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virBitmap *pcpumap = NULL;
+virDomainVcpuDef *vcpuinfo = NULL;
+g_autoptr(virCHDriverConfig) cfg = NUL

[libvirt PATCH v2 07/17] ch_driver, ch_domain: vcpu info getter callbacks

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c |  25 +
 src/ch/ch_domain.h |   4 ++
 src/ch/ch_driver.c | 137 +
 3 files changed, 166 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 2769d758fe..d81221679e 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -334,3 +334,28 @@ virCHDomainGetMonitor(virDomainObj * vm)
 {
 return CH_DOMAIN_PRIVATE(vm)->monitor;
 }
+
+pid_t
+virCHDomainGetVcpuPid(virDomainObj * vm, unsigned int vcpuid)
+{
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, vcpuid);
+
+return CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid;
+}
+
+bool
+virCHDomainHasVcpuPids(virDomainObj * vm)
+{
+size_t i;
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virDomainVcpuDef *vcpu;
+
+for (i = 0; i < maxvcpus; i++) {
+vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid > 0)
+return true;
+}
+
+return false;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 75b9933130..d9c9d34a19 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -82,3 +82,7 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob 
job)
 
 void
 virCHDomainObjEndJob(virDomainObj *obj);
+
+int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
+bool virCHDomainHasVcpuPids(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 75c6a15dd6..52c88571af 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -944,6 +944,140 @@ chStateInitialize(bool privileged,
 return ret;
 }
 
+static int
+chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
+virDomainObj *vm;
+virDomainDef *def;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_GUEST, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+return -1;
+
+if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
+ret = virDomainDefGetVcpusMax(def);
+else
+ret = virDomainDefGetVcpus(def);
+
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainGetMaxVcpus(virDomainPtr dom)
+{
+return chDomainGetVcpusFlags(dom,
+ (VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+static int
+chDomainHelperGetVcpus(virDomainObj * vm,
+   virVcpuInfoPtr info,
+   unsigned long long *cpuwait,
+   int maxinfo, unsigned char *cpumaps, int maplen)
+{
+size_t ncpuinfo = 0;
+size_t i;
+
+if (maxinfo == 0)
+return 0;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (info)
+memset(info, 0, sizeof(*info) * maxinfo);
+
+if (cpumaps)
+memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; 
i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+pid_t vcpupid = virCHDomainGetVcpuPid(vm, i);
+virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
+
+if (!vcpu->online)
+continue;
+
+if (info) {
+vcpuinfo->number = i;
+vcpuinfo->state = VIR_VCPU_RUNNING;
+if (virProcessGetStatInfo(&vcpuinfo->cpuTime,
+  &vcpuinfo->cpu, NULL,
+  vm->pid, vcpupid) < 0) {
+virReportSystemError(errno, "%s",
+ _
+ ("cannot get vCPU placement & pCPU 
time"));
+return -1;
+}
+}
+
+if (cpumaps) {
+unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
+g_autoptr(virBitmap) map = NULL;
+
+if (!(map = virProcessGetAffinity(vcpupid)))
+return -1;
+
+virBitmapToDataBuf(map, cpumap, maplen);
+}
+
+if (cpuwait) {
+if (virProcessGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) 
<
+0)
+return -1;
+}
+
+ncpuinfo++;
+}
+
+return ncpuinfo;
+}
+
+static int
+chDomainGetVcpus(virDomainPtr dom,
+ virVcpuInfoPtr info,
+ int maxinfo, unsigned char *cpumaps, int maplen)
+{
+ 

[libvirt PATCH v2 14/17] ch_driver: enable typed param string for numatune

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Enable support of VIR_DRV_FEATURE_TYPED_PARAM_STRING to enable numatune

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 400dfee766..c6dcc33f5e 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -946,6 +946,36 @@ chStateInitialize(bool privileged,
 return ret;
 }
 
+/* Which features are supported by this driver? */
+static int
+chConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+return -1;
+
+switch ((virDrvFeature) feature) {
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
+}
+}
+
 static int
 chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
 {
@@ -1291,6 +1321,7 @@ static virHypervisorDriver chHypervisorDriver = {
 .connectListAllDomains = chConnectListAllDomains,   /* 7.5.0 */
 .connectListDomains = chConnectListDomains, /* 7.5.0 */
 .connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
+.connectSupportsFeature = chConnectSupportsFeature, /* 7.11.0 */
 .domainCreateXML = chDomainCreateXML,   /* 7.5.0 */
 .domainCreate = chDomainCreate, /* 7.5.0 */
 .domainCreateWithFlags = chDomainCreateWithFlags,   /* 7.5.0 */
-- 
2.27.0




[libvirt PATCH v2 15/17] ch_driver: add numatune callbacks for CH driver

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 316 ++---
 1 file changed, 297 insertions(+), 19 deletions(-)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index c6dcc33f5e..8c14829d2a 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
 #include "viruri.h"
 #include "virutil.h"
 #include "viruuid.h"
+#include "virnuma.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -954,25 +955,25 @@ chConnectSupportsFeature(virConnectPtr conn, int feature)
 return -1;
 
 switch ((virDrvFeature) feature) {
-case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
-return 1;
-case VIR_DRV_FEATURE_MIGRATION_V2:
-case VIR_DRV_FEATURE_MIGRATION_V3:
-case VIR_DRV_FEATURE_MIGRATION_P2P:
-case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
-case VIR_DRV_FEATURE_FD_PASSING:
-case VIR_DRV_FEATURE_XML_MIGRATABLE:
-case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
-case VIR_DRV_FEATURE_MIGRATION_PARAMS:
-case VIR_DRV_FEATURE_MIGRATION_DIRECT:
-case VIR_DRV_FEATURE_MIGRATION_V1:
-case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
-case VIR_DRV_FEATURE_REMOTE:
-case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
-case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
-case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
-default:
-return 0;
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
 }
 }
 
@@ -1308,6 +1309,281 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+  virTypedParameterPtr params,
+  int *nparams,
+  unsigned int flags)
+{
+size_t i;
+virDomainObj *vm = NULL;
+virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+virCHDomainObjPrivate *priv;
+g_autofree char *nodeset = NULL;
+int ret = -1;
+virDomainDef *def = NULL;
+bool live = false;
+virBitmap *autoNodeset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (!(vm = virCHDomainObjFromDomain(dom)))
+return -1;
+priv = vm->privateData;
+
+if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live)
+autoNodeset = priv->autoNodeset;
+
+if ((*nparams) == 0) {
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+goto cleanup;
+}
+
+for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+virMemoryParameterPtr param = ¶ms[i];
+
+switch (i) {
+case 0: /* fill numa mode here */
+ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+VIR_TYPED_PARAM_INT, tmpmode) < 0)
+goto cleanup;
+
+break;
+
+case 1: /* fill numa nodeset here */
+nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, 
-1);
+
+if (!nodeset ||
+virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+VIR_TYPED_PARAM_STRING, nodeset) < 0)
+goto cleanup;
+
+nodeset = NULL;
+break;
+
+/* coverity[dead_error_begin] */
+default:
+break;
+/* should not hit here */
+}
+}
+
+if (*nparams > CH_NB_NUMA_PARAM)
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+  virBitmap *nodeset)
+{
+virCgroup *cgroup_temp = NULL;
+virCHDomainObjPrivate *priv = vm->privateData;
+g_autofree char *node

[libvirt PATCH v2 08/17] ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Add domainGetVcpuPinInfo and nodeGetCPUMap callbacks to ch driver

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.h | 12 +--
 src/ch/ch_driver.c | 54 +-
 2 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index d9c9d34a19..e35777a9ec 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -23,6 +23,7 @@
 #include "ch_conf.h"
 #include "ch_monitor.h"
 #include "virchrdev.h"
+#include "vircgroup.h"
 
 /* Give up waiting for mutex after 30 seconds */
 #define CH_JOB_WAIT_TIME (1000ull * 30)
@@ -52,9 +53,16 @@ typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate;
 struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
-virCHMonitor *monitor;
+virChrdevs *chrdevs;
+
+virCgroup *cgroup;
 
- virChrdevs *chrdevs;
+virCHDriver *driver;
+virCHMonitor *monitor;
+char *machineName;
+virBitmap *autoNodeset;
+virBitmap *autoCpuset;
+virChrdevs *devs;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 52c88571af..86d2776354 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -984,7 +984,56 @@ chDomainGetMaxVcpus(virDomainPtr dom)
 }
 
 static int
-chDomainHelperGetVcpus(virDomainObj * vm,
+chDomainGetVcpuPinInfo(virDomain * dom,
+   int ncpumaps,
+   unsigned char *cpumaps, int maplen, unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+bool live;
+int ret = -1;
+
+g_autoptr(virBitmap) hostcpus = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (!(hostcpus = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+
+if (live)
+autoCpuset = CH_DOMAIN_PRIVATE(vm)->autoCpuset;
+
+ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
+   hostcpus, autoCpuset);
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chNodeGetCPUMap(virConnectPtr conn,
+unsigned char **cpumap,
+unsigned int *online, unsigned int flags)
+{
+if (virNodeGetCPUMapEnsureACL(conn) < 0)
+return -1;
+
+return virHostCPUGetMap(cpumap, online, flags);
+}
+
+
+static int
+chDomainHelperGetVcpus(virDomainObj *vm,
virVcpuInfoPtr info,
unsigned long long *cpuwait,
int maxinfo, unsigned char *cpumaps, int maplen)
@@ -1030,6 +1079,7 @@ chDomainHelperGetVcpus(virDomainObj * vm,
 
 if (cpumaps) {
 unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
+
 g_autoptr(virBitmap) map = NULL;
 
 if (!(map = virProcessGetAffinity(vcpupid)))
@@ -1117,6 +1167,8 @@ static virHypervisorDriver chHypervisorDriver = {
 .domainGetVcpus = chDomainGetVcpus, /* 7.11.0 */
 .domainGetVcpusFlags = chDomainGetVcpusFlags,   /* 7.11.0 */
 .domainGetMaxVcpus = chDomainGetMaxVcpus,   /* 7.11.0 */
+.domainGetVcpuPinInfo = chDomainGetVcpuPinInfo, /* 7.11.0 */
+.nodeGetCPUMap = chNodeGetCPUMap,   /* 7.11.0 */
 };
 
 static virConnectDriver chConnectDriver = {
-- 
2.27.0




[libvirt PATCH v2 05/17] ch_domain: add methods to manage private vcpu data

2021-12-02 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 50 +-
 src/ch/ch_domain.h | 11 ++
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 7bfe950822..2769d758fe 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -159,11 +159,6 @@ virCHDomainObjPrivateFree(void *data)
 g_free(priv);
 }
 
-virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
-.alloc = virCHDomainObjPrivateAlloc,
-.free = virCHDomainObjPrivateFree,
-};
-
 static int
 virCHDomainDefPostParseBasic(virDomainDef * def, void *opaque G_GNUC_UNUSED)
 {
@@ -179,6 +174,45 @@ virCHDomainDefPostParseBasic(virDomainDef * def, void 
*opaque G_GNUC_UNUSED)
 return 0;
 }
 
+static virClass *virCHDomainVcpuPrivateClass;
+static void virCHDomainVcpuPrivateDispose(void *obj);
+
+static int
+virCHDomainVcpuPrivateOnceInit(void)
+{
+if (!VIR_CLASS_NEW(virCHDomainVcpuPrivate, virClassForObject()))
+return -1;
+
+return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virCHDomainVcpuPrivate);
+
+static virObject *
+virCHDomainVcpuPrivateNew(void)
+{
+virCHDomainVcpuPrivate *priv;
+
+if (virCHDomainVcpuPrivateInitialize() < 0)
+return NULL;
+
+if (!(priv = virObjectNew(virCHDomainVcpuPrivateClass)))
+return NULL;
+
+return (virObject *) priv;
+}
+
+
+static void
+virCHDomainVcpuPrivateDispose(void *obj)
+{
+virCHDomainVcpuPrivate *priv = obj;
+
+priv->tid = 0;
+
+return;
+}
+
 static int
 virCHDomainDefPostParse(virDomainDef * def,
 unsigned int parseFlags G_GNUC_UNUSED,
@@ -196,6 +230,12 @@ virCHDomainDefPostParse(virDomainDef * def,
 return 0;
 }
 
+virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
+.alloc = virCHDomainObjPrivateAlloc,
+.free = virCHDomainObjPrivateFree,
+.vcpuNew = virCHDomainVcpuPrivateNew,
+};
+
 static int
 chValidateDomainDeviceDef(const virDomainDeviceDef * dev,
   const virDomainDef * def G_GNUC_UNUSED,
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 04d19398b4..75b9933130 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -62,6 +62,17 @@ struct _virCHDomainObjPrivate {
 
 virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
 
+typedef struct _virCHDomainVcpuPrivate virCHDomainVcpuPrivate;
+struct _virCHDomainVcpuPrivate {
+virObject parent;
+
+pid_t tid; /* vcpu thread id */
+virTristateBool halted;
+};
+
+#define CH_DOMAIN_VCPU_PRIVATE(vcpu) \
+((virCHDomainVcpuPrivate *) (vcpu)->privateData)
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH v2 02/17] util: Helper functions to get process info

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/libvirt_private.syms |   2 +
 src/qemu/qemu_driver.c   | 116 ++-
 src/util/virprocess.c| 108 
 src/util/virprocess.h|   5 ++
 4 files changed, 120 insertions(+), 111 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b98cb0f66d..e0c4fba522 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3099,8 +3099,10 @@ virProcessGetAffinity;
 virProcessGetMaxMemLock;
 virProcessGetNamespaces;
 virProcessGetPids;
+virProcessGetSchedInfo;
 virProcessGetStartTime;
 virProcessGetStat;
+virProcessGetStatInfo;
 virProcessGroupGet;
 virProcessGroupKill;
 virProcessKill;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4e680bc0a7..a7088d3a66 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1323,113 +1323,6 @@ qemuGetSchedstatDelay(unsigned long long *cpudelay,
 return 0;
 }
 
-
-static int
-qemuGetSchedInfo(unsigned long long *cpuWait,
- pid_t pid, pid_t tid)
-{
-g_autofree char *proc = NULL;
-g_autofree char *data = NULL;
-g_auto(GStrv) lines = NULL;
-size_t i;
-double val;
-
-*cpuWait = 0;
-
-/* In general, we cannot assume pid_t fits in int; but /proc parsing
- * is specific to Linux where int works fine.  */
-if (tid)
-proc = g_strdup_printf("/proc/%d/task/%d/sched", (int)pid, (int)tid);
-else
-proc = g_strdup_printf("/proc/%d/sched", (int)pid);
-if (!proc)
-return -1;
-
-/* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
-if (access(proc, R_OK) < 0) {
-return 0;
-}
-
-if (virFileReadAll(proc, (1<<16), &data) < 0)
-return -1;
-
-lines = g_strsplit(data, "\n", 0);
-if (!lines)
-return -1;
-
-for (i = 0; lines[i] != NULL; i++) {
-const char *line = lines[i];
-
-/* Needs CONFIG_SCHEDSTATS. The second check
- * is the old name the kernel used in past */
-if (STRPREFIX(line, "se.statistics.wait_sum") ||
-STRPREFIX(line, "se.wait_sum")) {
-line = strchr(line, ':');
-if (!line) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Missing separator in sched info '%s'"),
-   lines[i]);
-return -1;
-}
-line++;
-while (*line == ' ')
-line++;
-
-if (virStrToDouble(line, NULL, &val) < 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("Unable to parse sched info value '%s'"),
-   line);
-return -1;
-}
-
-*cpuWait = (unsigned long long)(val * 100);
-break;
-}
-}
-
-return 0;
-}
-
-
-static int
-qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
-   pid_t pid, pid_t tid)
-{
-g_auto(GStrv) proc_stat = virProcessGetStat(pid, tid);
-unsigned long long usertime = 0, systime = 0;
-long rss = 0;
-int cpu = 0;
-
-if (!proc_stat ||
-virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_UTIME], NULL, 10, 
&usertime) < 0 ||
-virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_STIME], NULL, 10, 
&systime) < 0 ||
-virStrToLong_l(proc_stat[VIR_PROCESS_STAT_RSS], NULL, 10, &rss) < 0 ||
-virStrToLong_i(proc_stat[VIR_PROCESS_STAT_PROCESSOR], NULL, 10, &cpu) 
< 0) {
-VIR_WARN("cannot parse process status data");
-}
-
-/* We got jiffies
- * We want nanoseconds
- * _SC_CLK_TCK is jiffies per second
- * So calculate thus
- */
-if (cpuTime)
-*cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
-/ (unsigned long long)sysconf(_SC_CLK_TCK);
-if (lastCpu)
-*lastCpu = cpu;
-
-if (vm_rss)
-*vm_rss = rss * virGetSystemPageSizeKB();
-
-
-VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
-  (int)pid, tid, usertime, systime, cpu, rss);
-
-return 0;
-}
-
-
 static int
 qemuDomainHelperGetVcpus(virDomainObj *vm,
  virVcpuInfoPtr info,
@@ -1469,7 +1362,7 @@ qemuDomainHelperGetVcpus(virDomainObj *vm,
 vcpuinfo->number = i;
 vcpuinfo->state = VIR_VCPU_RUNNING;
 
-if (qemuGetProcessInfo(&vcpuinfo->cpuTime,
+if (virProcessGetStatInfo(&vcpuinfo->cpuTime,
&vcpuinfo->cpu, NULL,
vm->pid, vcpupid) < 0) {
 virReportSystemError(errno, "%s",
@@ -1490,7 +1383,7 @@ qemuDomainHel

[libvirt PATCH v2 03/17] ch_domain: fix indentation in ch_domain

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 130 ++---
 1 file changed, 64 insertions(+), 66 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index dd4de9e1ea..44f7d26ca4 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -30,16 +30,12 @@
 
 VIR_ENUM_IMPL(virCHDomainJob,
   CH_JOB_LAST,
-  "none",
-  "query",
-  "destroy",
-  "modify",
-);
+  "none", "query", "destroy", "modify",);
 
 VIR_LOG_INIT("ch.ch_domain");
 
 static int
-virCHDomainObjInitJob(virCHDomainObjPrivate *priv)
+virCHDomainObjInitJob(virCHDomainObjPrivate * priv)
 {
 memset(&priv->job, 0, sizeof(priv->job));
 
@@ -50,7 +46,7 @@ virCHDomainObjInitJob(virCHDomainObjPrivate *priv)
 }
 
 static void
-virCHDomainObjResetJob(virCHDomainObjPrivate *priv)
+virCHDomainObjResetJob(virCHDomainObjPrivate * priv)
 {
 struct virCHDomainJobObj *job = &priv->job;
 
@@ -59,7 +55,7 @@ virCHDomainObjResetJob(virCHDomainObjPrivate *priv)
 }
 
 static void
-virCHDomainObjFreeJob(virCHDomainObjPrivate *priv)
+virCHDomainObjFreeJob(virCHDomainObjPrivate * priv)
 {
 ignore_value(virCondDestroy(&priv->job.cond));
 }
@@ -74,7 +70,7 @@ virCHDomainObjFreeJob(virCHDomainObjPrivate *priv)
  * Successful calls must be followed by EndJob eventually.
  */
 int
-virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob job)
+virCHDomainObjBeginJob(virDomainObj * obj, enum virCHDomainJob job)
 {
 virCHDomainObjPrivate *priv = obj->privateData;
 unsigned long long now;
@@ -121,13 +117,12 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum 
virCHDomainJob job)
  * earlier virCHDomainBeginJob() call
  */
 void
-virCHDomainObjEndJob(virDomainObj *obj)
+virCHDomainObjEndJob(virDomainObj * obj)
 {
 virCHDomainObjPrivate *priv = obj->privateData;
 enum virCHDomainJob job = priv->job.active;
 
-VIR_DEBUG("Stopping job: %s",
-  virCHDomainJobTypeToString(job));
+VIR_DEBUG("Stopping job: %s", virCHDomainJobTypeToString(job));
 
 virCHDomainObjResetJob(priv);
 virCondSignal(&priv->job.cond);
@@ -170,8 +165,7 @@ virDomainXMLPrivateDataCallbacks 
virCHDriverPrivateDataCallbacks = {
 };
 
 static int
-virCHDomainDefPostParseBasic(virDomainDef *def,
- void *opaque G_GNUC_UNUSED)
+virCHDomainDefPostParseBasic(virDomainDef * def, void *opaque G_GNUC_UNUSED)
 {
 /* check for emulator and create a default one if needed */
 if (!def->emulator) {
@@ -186,71 +180,70 @@ virCHDomainDefPostParseBasic(virDomainDef *def,
 }
 
 static int
-virCHDomainDefPostParse(virDomainDef *def,
+virCHDomainDefPostParse(virDomainDef * def,
 unsigned int parseFlags G_GNUC_UNUSED,
-void *opaque,
-void *parseOpaque G_GNUC_UNUSED)
+void *opaque, void *parseOpaque G_GNUC_UNUSED)
 {
 virCHDriver *driver = opaque;
+
 g_autoptr(virCaps) caps = virCHDriverGetCapabilities(driver, false);
 if (!caps)
 return -1;
 if (!virCapabilitiesDomainSupported(caps, def->os.type,
-def->os.arch,
-def->virtType))
+def->os.arch, def->virtType))
 return -1;
 
 return 0;
 }
 
 static int
-chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
-  const virDomainDef *def G_GNUC_UNUSED,
+chValidateDomainDeviceDef(const virDomainDeviceDef * dev,
+  const virDomainDef * def G_GNUC_UNUSED,
   void *opaque G_GNUC_UNUSED,
   void *parseOpaque G_GNUC_UNUSED)
 {
-switch ((virDomainDeviceType)dev->type) {
-case VIR_DOMAIN_DEVICE_DISK:
-case VIR_DOMAIN_DEVICE_NET:
-case VIR_DOMAIN_DEVICE_MEMORY:
-case VIR_DOMAIN_DEVICE_VSOCK:
-case VIR_DOMAIN_DEVICE_CONTROLLER:
-case VIR_DOMAIN_DEVICE_CHR:
-break;
-
-case VIR_DOMAIN_DEVICE_LEASE:
-case VIR_DOMAIN_DEVICE_FS:
-case VIR_DOMAIN_DEVICE_INPUT:
-case VIR_DOMAIN_DEVICE_SOUND:
-case VIR_DOMAIN_DEVICE_VIDEO:
-case VIR_DOMAIN_DEVICE_HOSTDEV:
-case VIR_DOMAIN_DEVICE_WATCHDOG:
-case VIR_DOMAIN_DEVICE_GRAPHICS:
-case VIR_DOMAIN_DEVICE_HUB:
-case VIR_DOMAIN_DEVICE_REDIRDEV:
-case VIR_DOMAIN_DEVICE_SMARTCARD:
-case VIR_DOMAIN_DEVICE_MEMBALLOON:
-case VIR_DOMAIN_DEVICE_NVRAM:
-case VIR_DOMAIN_DEVICE_RNG:
-case VIR_DOMAIN_DEVICE_SHMEM:
-case VIR_DOMAIN_DEVICE_TPM:
-case VIR_DOMAIN_DEVICE_PANIC:
-case VIR_DOMAIN_DEVICE_IOMMU:
-case VIR_DOMAIN_DEVICE_AUDIO:
-virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-   _("C

[libvirt PATCH v2 09/17] ch_monitor: fix indentation in ch_monitor.c

2021-12-02 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 301 +++-
 1 file changed, 161 insertions(+), 140 deletions(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 12c10da874..68fa5b30aa 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -42,7 +42,8 @@ VIR_LOG_INIT("ch.ch_monitor");
 static virClass *virCHMonitorClass;
 static void virCHMonitorDispose(void *obj);
 
-static int virCHMonitorOnceInit(void)
+static int
+virCHMonitorOnceInit(void)
 {
 if (!VIR_CLASS_NEW(virCHMonitor, virClassForObjectLockable()))
 return -1;
@@ -52,11 +53,11 @@ static int virCHMonitorOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(virCHMonitor);
 
-int virCHMonitorShutdownVMM(virCHMonitor *mon);
-int virCHMonitorPutNoContent(virCHMonitor *mon, const char *endpoint);
+int virCHMonitorShutdownVMM(virCHMonitor * mon);
+int virCHMonitorPutNoContent(virCHMonitor * mon, const char *endpoint);
 
 static int
-virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef *vmdef)
+virCHMonitorBuildCPUJson(virJSONValue * content, virDomainDef * vmdef)
 {
 g_autoptr(virJSONValue) cpus = NULL;
 unsigned int maxvcpus = 0;
@@ -64,7 +65,7 @@ virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef 
*vmdef)
 virDomainVcpuDef *vcpu;
 size_t i;
 
-/* count maximum allowed number vcpus and enabled vcpus when boot.*/
+/* count maximum allowed number vcpus and enabled vcpus when boot. */
 maxvcpus = virDomainDefGetVcpusMax(vmdef);
 for (i = 0; i < maxvcpus; i++) {
 vcpu = virDomainDefGetVcpu(vmdef, i);
@@ -76,7 +77,8 @@ virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef 
*vmdef)
 cpus = virJSONValueNewObject();
 if (virJSONValueObjectAppendNumberInt(cpus, "boot_vcpus", nvcpus) < 0)
 return -1;
-if (virJSONValueObjectAppendNumberInt(cpus, "max_vcpus", 
vmdef->maxvcpus) < 0)
+if (virJSONValueObjectAppendNumberInt
+(cpus, "max_vcpus", vmdef->maxvcpus) < 0)
 return -1;
 if (virJSONValueObjectAppend(content, "cpus", &cpus) < 0)
 return -1;
@@ -86,7 +88,7 @@ virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef 
*vmdef)
 }
 
 static int
-virCHMonitorBuildPTYJson(virJSONValue *content, virDomainDef *vmdef)
+virCHMonitorBuildPTYJson(virJSONValue * content, virDomainDef * vmdef)
 {
 if (vmdef->nconsoles) {
 g_autoptr(virJSONValue) pty = virJSONValueNewObject();
@@ -108,7 +110,7 @@ virCHMonitorBuildPTYJson(virJSONValue *content, 
virDomainDef *vmdef)
 }
 
 static int
-virCHMonitorBuildKernelRelatedJson(virJSONValue *content, virDomainDef *vmdef)
+virCHMonitorBuildKernelRelatedJson(virJSONValue * content, virDomainDef * 
vmdef)
 {
 g_autoptr(virJSONValue) kernel = virJSONValueNewObject();
 g_autoptr(virJSONValue) cmdline = virJSONValueNewObject();
@@ -119,21 +121,24 @@ virCHMonitorBuildKernelRelatedJson(virJSONValue *content, 
virDomainDef *vmdef)
_("Kernel image path in this domain is not defined"));
 return -1;
 } else {
-if (virJSONValueObjectAppendString(kernel, "path", vmdef->os.kernel) < 
0)
+if (virJSONValueObjectAppendString(kernel, "path", vmdef->os.kernel) <
+0)
 return -1;
 if (virJSONValueObjectAppend(content, "kernel", &kernel) < 0)
 return -1;
 }
 
 if (vmdef->os.cmdline) {
-if (virJSONValueObjectAppendString(cmdline, "args", vmdef->os.cmdline) 
< 0)
+if (virJSONValueObjectAppendString(cmdline, "args", vmdef->os.cmdline) 
<
+0)
 return -1;
 if (virJSONValueObjectAppend(content, "cmdline", &cmdline) < 0)
 return -1;
 }
 
 if (vmdef->os.initrd != NULL) {
-if (virJSONValueObjectAppendString(initramfs, "path", 
vmdef->os.initrd) < 0)
+if (virJSONValueObjectAppendString(initramfs, "path", vmdef->os.initrd)
+< 0)
 return -1;
 if (virJSONValueObjectAppend(content, "initramfs", &initramfs) < 0)
 return -1;
@@ -143,14 +148,16 @@ virCHMonitorBuildKernelRelatedJson(virJSONValue *content, 
virDomainDef *vmdef)
 }
 
 static int
-virCHMonitorBuildMemoryJson(virJSONValue *content, virDomainDef *vmdef)
+virCHMonitorBuildMemoryJson(virJSONValue * content, virDomainDef * vmdef)
 {
-unsigned long long total_memory = virDomainDefGetMemoryInitial(vmdef) * 
1024;
+unsigned long long total_memory =
+virDomainDefGetMemoryInitial(vmdef) * 1024;
 
 if (total_memory != 0) {
 g_autoptr(virJSONValue) memory = virJSONValueNewObject();
 
-if (virJSONValueObjectAppendNumberUlong(memory, "size", total_memory) 
< 0)
+

Re: [libvirt PATCH 00/13] cgroup and thread management in ch driver.

2021-11-16 Thread Praveen K Paladugu




On 10/24/2021 9:59 PM, Yan Fu wrote:

Hi,

Could you give a reference link for ch driver please?

Thanks,
Yan Fu

Sorry about the delay with my response. What do you mean by a

reference link?





On Fri, Oct 22, 2021 at 11:43 PM Praveen K Paladugu 
mailto:pra...@linux.microsoft.com>> wrote:


This patchset adds support for cgroup management of ch threads. This
version
correctly manages cgroups for vcpu and emulator threads created by
ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for
pinning
vcpu and emulator threads to selected host cpus.

Praveen K Paladugu (2):
   ch_process: Setup emulator and iothread settings
   ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (11):
   util: Helper functions to get process info
   ch: Explicitly link to virt_util_lib
   ch_domain: add virCHDomainGetMonitor helper method
   ch_domain: add methods to manage private vcpu data
   ch_driver,ch_domain: vcpu info getter callbacks
   ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap
   ch_monitor: Get nicindexes in prep for cgroup mgmt
   ch_cgroup: methods for cgroup mgmt in ch driver
   ch_driver,ch_domain: vcpupin callback in ch driver
   ch_driver: enable typed param string for numatune
   ch_driver: add numatune callbacks for CH driver

  po/POTFILES.in        |   1 +
  src/ch/ch_cgroup.c    | 457 
  src/ch/ch_cgroup.h    |  45 +++
  src/ch/ch_conf.c      |   2 +
  src/ch/ch_conf.h      |   9 +-
  src/ch/ch_domain.c    | 170 -
  src/ch/ch_domain.h    |  32 +-
  src/ch/ch_driver.c    | 810 +-
  src/ch/ch_monitor.c   | 254 -
  src/ch/ch_monitor.h   |  60 +++-
  src/ch/ch_process.c   | 368 ++-
  src/ch/ch_process.h   |   3 +
  src/ch/meson.build    |   6 +
  src/util/virprocess.c | 136 +++
  src/util/virprocess.h |   5 +
  15 files changed, 2329 insertions(+), 29 deletions(-)
  create mode 100644 src/ch/ch_cgroup.c
  create mode 100644 src/ch/ch_cgroup.h

-- 
2.27.0





--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 08/13] ch_cgroup: methods for cgroup mgmt in ch driver

2021-11-15 Thread Praveen K Paladugu




On 10/29/2021 7:31 AM, Michal Prívozník wrote:

On 10/22/21 5:37 PM, Praveen K Paladugu wrote:

From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
  po/POTFILES.in  |   1 +
  src/ch/ch_cgroup.c  | 457 
  src/ch/ch_cgroup.h  |  45 +
  src/ch/ch_conf.c|   2 +
  src/ch/ch_conf.h|   4 +-
  src/ch/ch_domain.c  |  33 
  src/ch/ch_domain.h  |   3 +-
  src/ch/ch_monitor.c | 125 ++--
  src/ch/ch_monitor.h |  54 +-
  src/ch/ch_process.c | 288 +++-
  src/ch/ch_process.h |   3 +
  src/ch/meson.build  |   2 +
  12 files changed, 991 insertions(+), 26 deletions(-)
  create mode 100644 src/ch/ch_cgroup.c
  create mode 100644 src/ch/ch_cgroup.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index b554cf08ca..3a8db501bc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,6 +19,7 @@
  @SRCDIR@src/bhyve/bhyve_parse_command.c
  @SRCDIR@src/bhyve/bhyve_process.c
  @SRCDIR@src/ch/ch_conf.c
+@SRCDIR@src/ch/ch_cgroup.c
  @SRCDIR@src/ch/ch_domain.c
  @SRCDIR@src/ch/ch_driver.c
  @SRCDIR@src/ch/ch_monitor.c
diff --git a/src/ch/ch_cgroup.c b/src/ch/ch_cgroup.c
new file mode 100644
index 00..6be2184cf1
--- /dev/null
+++ b/src/ch/ch_cgroup.c
@@ -0,0 +1,457 @@
+/*
+ * ch_cgroup.c: CH cgroup management


This file is a verbatim copy of qemu_cgroup.c (except for some
formatting shenanigans). I wonder whether instead of copying code we can
move it under hypervisor agnostic location (src/hypervisor/) and then
only call respective functions from either of drivers. What do you think?

Michal



I started refactoring this commit to have shared methods between qemu 
and ch drviers for cgroup management. While doing so, I realized, I 
still need a mechanism to identify what the underlying driver is : ch/qemu.


An example of it is the prefix for the cgroup to be created. Ch driver 
is configured to have a prefix of "ch", while qemu driver configures the 
prefix of the cgroup name to "qemu".


What is the best way to detect the underlying driver from 
src/hypervisor?  One way I could think of it is to extend 
virQEMUDriver/virtCHDriver struct to also have a driver name which will 
be checked from these shared methods. Any other recommendations for this 
check?




--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 01/13] util: Helper functions to get process info

2021-11-11 Thread Praveen K Paladugu




On 11/11/2021 3:25 AM, Michal Prívozník wrote:

On 11/10/21 9:49 PM, Praveen K Paladugu wrote:



On 10/29/2021 7:31 AM, Michal Prívozník wrote:

On 10/22/21 5:37 PM, Praveen K Paladugu wrote:

From: Vineeth Pillai 

These helper methods are used to capture vcpu information
in ch driver.

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
   src/util/virprocess.c | 136 ++
   src/util/virprocess.h |   5 ++
   2 files changed, 141 insertions(+)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 6de3f36f52..0164d70df6 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -1721,3 +1721,139 @@ virProcessSetScheduler(pid_t pid G_GNUC_UNUSED,
   }
     #endif /* !WITH_SCHED_SETSCHEDULER */
+
+/*
+TODO: This method was cloned from qemuGetProcessInfo in
src/qemu/qemu_driver.c.
+Need to refactor qemu driver to use this shared function.


There's no harm in doing that in this patch. In fact, it's desired. You
can move a qemu function into src/util, rename it and fix all places
where it is called, all in one patch.

Also, please don't forget to export this function in
src/libvirt_private.syms.


I am working on this now. Will make this part of next version.

+*/
+int
+virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu,
long *vm_rss,
+   pid_t pid, pid_t tid)


Indentation's off. I've noticed other patches in the series suffer from
mis-indentation too. Please fix that in another version.


Regarding indentation, many of these patches add/modify existing files.
Running indent will modify sections of the files not relevant to the
code changes in this patch set.
Should I run "indent" either way? Or should I make all indentation
changes for all files as a single commit?


We like to have one semantic change per commit. Therefore, if you are
fixing indentation in a code that's unrelated (i.e. you are fixing
indentation in a function you are not touching) then that's considered
as another semantic change.

What I was aiming at is that new code should be indented well from the
beginning. That's obviously one semantic change and as such should be in
one patch (i.e. new code that's well formatted).

Have I answered your question or did I misunderstand?

Michal


Thanks Michal.

I will keep this in mind for V2 of this patch set.

--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 01/13] util: Helper functions to get process info

2021-11-11 Thread Praveen K Paladugu




On 11/11/2021 3:19 AM, Daniel P. Berrangé wrote:

On Wed, Nov 10, 2021 at 02:49:57PM -0600, Praveen K Paladugu wrote:



On 10/29/2021 7:31 AM, Michal Prívozník wrote:

On 10/22/21 5:37 PM, Praveen K Paladugu wrote:

From: Vineeth Pillai 

These helper methods are used to capture vcpu information
in ch driver.

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
   src/util/virprocess.c | 136 ++
   src/util/virprocess.h |   5 ++
   2 files changed, 141 insertions(+)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 6de3f36f52..0164d70df6 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -1721,3 +1721,139 @@ virProcessSetScheduler(pid_t pid G_GNUC_UNUSED,
   }
   #endif /* !WITH_SCHED_SETSCHEDULER */
+
+/*
+TODO: This method was cloned from qemuGetProcessInfo in src/qemu/qemu_driver.c.
+Need to refactor qemu driver to use this shared function.


There's no harm in doing that in this patch. In fact, it's desired. You
can move a qemu function into src/util, rename it and fix all places
where it is called, all in one patch.

Also, please don't forget to export this function in
src/libvirt_private.syms.


I am working on this now. Will make this part of next version.

+*/
+int
+virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
+   pid_t pid, pid_t tid)


Indentation's off. I've noticed other patches in the series suffer from
mis-indentation too. Please fix that in another version.


Regarding indentation, many of these patches add/modify existing files.
Running indent will modify sections of the files not relevant to the code
changes in this patch set.
Should I run "indent" either way? Or should I make all indentation changes
for all files as a single commit?


If thre are whitespace bugs in existing code, then it is preferrable to
fix them in a standalone commit, so it is easily distinguished from
functional changes.

Regards,
Daniel

Make sense Daniel. If any of the existing files don't have correct 
indentation, I will fix the original file in a separate commit and add 
my changes on top.



--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 01/13] util: Helper functions to get process info

2021-11-10 Thread Praveen K Paladugu




On 10/29/2021 7:31 AM, Michal Prívozník wrote:

On 10/22/21 5:37 PM, Praveen K Paladugu wrote:

From: Vineeth Pillai 

These helper methods are used to capture vcpu information
in ch driver.

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
  src/util/virprocess.c | 136 ++
  src/util/virprocess.h |   5 ++
  2 files changed, 141 insertions(+)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 6de3f36f52..0164d70df6 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -1721,3 +1721,139 @@ virProcessSetScheduler(pid_t pid G_GNUC_UNUSED,
  }
  
  #endif /* !WITH_SCHED_SETSCHEDULER */

+
+/*
+TODO: This method was cloned from qemuGetProcessInfo in src/qemu/qemu_driver.c.
+Need to refactor qemu driver to use this shared function.


There's no harm in doing that in this patch. In fact, it's desired. You
can move a qemu function into src/util, rename it and fix all places
where it is called, all in one patch.

Also, please don't forget to export this function in
src/libvirt_private.syms.


I am working on this now. Will make this part of next version.

+*/
+int
+virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
+   pid_t pid, pid_t tid)


Indentation's off. I've noticed other patches in the series suffer from
mis-indentation too. Please fix that in another version.

Regarding indentation, many of these patches add/modify existing files. 
Running indent will modify sections of the files not relevant to the 
code changes in this patch set.
Should I run "indent" either way? Or should I make all indentation 
changes for all files as a single commit?



+{
+g_autofree char *proc = NULL;
+FILE *pidinfo;
+unsigned long long usertime = 0, systime = 0;


I wonder whether we should take this opportunity and declare these two
variables at one line each.


+long rss = 0;
+int cpu = 0;


Michal



--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 08/13] ch_cgroup: methods for cgroup mgmt in ch driver

2021-11-10 Thread Praveen K Paladugu




On 10/29/2021 7:31 AM, Michal Prívozník wrote:

On 10/22/21 5:37 PM, Praveen K Paladugu wrote:

From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
  po/POTFILES.in  |   1 +
  src/ch/ch_cgroup.c  | 457 
  src/ch/ch_cgroup.h  |  45 +
  src/ch/ch_conf.c|   2 +
  src/ch/ch_conf.h|   4 +-
  src/ch/ch_domain.c  |  33 
  src/ch/ch_domain.h  |   3 +-
  src/ch/ch_monitor.c | 125 ++--
  src/ch/ch_monitor.h |  54 +-
  src/ch/ch_process.c | 288 +++-
  src/ch/ch_process.h |   3 +
  src/ch/meson.build  |   2 +
  12 files changed, 991 insertions(+), 26 deletions(-)
  create mode 100644 src/ch/ch_cgroup.c
  create mode 100644 src/ch/ch_cgroup.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index b554cf08ca..3a8db501bc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,6 +19,7 @@
  @SRCDIR@src/bhyve/bhyve_parse_command.c
  @SRCDIR@src/bhyve/bhyve_process.c
  @SRCDIR@src/ch/ch_conf.c
+@SRCDIR@src/ch/ch_cgroup.c
  @SRCDIR@src/ch/ch_domain.c
  @SRCDIR@src/ch/ch_driver.c
  @SRCDIR@src/ch/ch_monitor.c
diff --git a/src/ch/ch_cgroup.c b/src/ch/ch_cgroup.c
new file mode 100644
index 00..6be2184cf1
--- /dev/null
+++ b/src/ch/ch_cgroup.c
@@ -0,0 +1,457 @@
+/*
+ * ch_cgroup.c: CH cgroup management


This file is a verbatim copy of qemu_cgroup.c (except for some
formatting shenanigans). I wonder whether instead of copying code we can
move it under hypervisor agnostic location (src/hypervisor/) and then
only call respective functions from either of drivers. What do you think?

Michal



Makes sense Michal.That is our intent as well. I posted this version to 
inputs on where would be a good place to move this common code. Will 
re-structure this commit to consolidate the code in ch and qemu drivers 
under src/hypervisor.


--
Regards,
Praveen K Paladugu




Re: [libvirt PATCH 01/13] util: Helper functions to get process info

2021-11-02 Thread Praveen K Paladugu

Hey Michal,

Thanks for your review of this patch set. I am Out of Office for 2 
weeks. I will send an updated patch set addressing all your comments, 
next week.


--
Regards,
Praveen K Paladugu



[libvirt PATCH 09/13] ch_driver, ch_domain: vcpupin callback in ch driver

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c |  30 +
 src/ch/ch_domain.h |   1 +
 src/ch/ch_driver.c | 151 +
 3 files changed, 182 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index d0aaeed1f4..9ad00583aa 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -20,6 +20,7 @@
 
 #include 
 
+#include "datatypes.h"
 #include "ch_domain.h"
 #include "domain_driver.h"
 #include "viralloc.h"
@@ -420,3 +421,32 @@ char *virCHDomainGetMachineName(virDomainObj *vm)
 
 return ret;
 }
+
+/**
+ * virCHDomainObjFromDomain:
+ * @domain: Domain pointer that has to be looked up
+ *
+ * This function looks up @domain and returns the appropriate virDomainObjPtr
+ * that has to be released by calling virDomainObjEndAPI().
+ *
+ * Returns the domain object with incremented reference counter which is locked
+ * on success, NULL otherwise.
+ */
+virDomainObj *
+virCHDomainObjFromDomain(virDomainPtr domain)
+{
+virDomainObj *vm;
+virCHDriver *driver = domain->conn->privateData;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
+if (!vm) {
+virUUIDFormat(domain->uuid, uuidstr);
+virReportError(VIR_ERR_NO_DOMAIN,
+   _("no domain with matching uuid '%s' (%s)"),
+   uuidstr, domain->name);
+return NULL;
+}
+
+return vm;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 2ce3e2cef3..db1451405b 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -95,3 +95,4 @@ pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int 
vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
 
 char *virCHDomainGetMachineName(virDomainObj *vm);
+virDomainObj *virCHDomainObjFromDomain(virDomain *domain);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index ca854da123..7f3cf6dbef 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -25,6 +25,7 @@
 #include "ch_driver.h"
 #include "ch_monitor.h"
 #include "ch_process.h"
+#include "ch_cgroup.h"
 #include "datatypes.h"
 #include "driver.h"
 #include "viraccessapicheck.h"
@@ -1141,6 +1142,154 @@ chDomainGetVcpus(virDomainPtr dom,
 return ret;
 }
 
+static int
+chDomainPinVcpuLive(virDomainObj *vm,
+virDomainDef *def,
+int vcpu,
+virCHDriver *driver,
+virCHDriverConfig *cfg,
+virBitmap *cpumap)
+{
+virBitmap *tmpmap = NULL;
+virDomainVcpuDef *vcpuinfo;
+virCHDomainObjPrivate *priv = vm->privateData;
+virCgroup *cgroup_vcpu = NULL;
+g_autofree char *str = NULL;
+int ret = -1;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+goto cleanup;
+}
+
+if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
+virReportError(VIR_ERR_INVALID_ARG,
+   _("vcpu %d is out of range of live cpu count %d"),
+   vcpu, virDomainDefGetVcpusMax(def));
+goto cleanup;
+}
+
+if (!(tmpmap = virBitmapNewCopy(cpumap)))
+goto cleanup;
+
+if (!(str = virBitmapFormat(cpumap)))
+goto cleanup;
+
+if (vcpuinfo->online) {
+/* Configure the corresponding cpuset cgroup before set affinity. */
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, vcpu,
+   false, &cgroup_vcpu) < 0)
+goto cleanup;
+if (chSetupCgroupCpusetCpus(cgroup_vcpu, cpumap) < 0)
+goto cleanup;
+}
+
+if (virProcessSetAffinity(virCHDomainGetVcpuPid(vm, vcpu), cpumap, 
false) < 0)
+goto cleanup;
+}
+
+virBitmapFree(vcpuinfo->cpumask);
+vcpuinfo->cpumask = tmpmap;
+tmpmap = NULL;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+virBitmapFree(tmpmap);
+virCgroupFree(cgroup_vcpu);
+return ret;
+}
+
+
+static int
+chDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virBitmap *pcpumap = NULL;
+virDomainVcpuDef *vcpuinfo = NULL;
+g_autoptr(virCHDriverConfig) cfg = NUL

[libvirt PATCH 10/13] ch_driver: enable typed param string for numatune

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Enable support of VIR_DRV_FEATURE_TYPED_PARAM_STRING to enable numatune

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 7f3cf6dbef..9ad23c1710 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -955,6 +955,36 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+/* Which features are supported by this driver? */
+static int
+chConnectSupportsFeature(virConnectPtr conn, int feature)
+{
+if (virConnectSupportsFeatureEnsureACL(conn) < 0)
+return -1;
+
+switch ((virDrvFeature) feature) {
+case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+return 1;
+case VIR_DRV_FEATURE_MIGRATION_V2:
+case VIR_DRV_FEATURE_MIGRATION_V3:
+case VIR_DRV_FEATURE_MIGRATION_P2P:
+case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
+case VIR_DRV_FEATURE_FD_PASSING:
+case VIR_DRV_FEATURE_XML_MIGRATABLE:
+case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
+case VIR_DRV_FEATURE_MIGRATION_PARAMS:
+case VIR_DRV_FEATURE_MIGRATION_DIRECT:
+case VIR_DRV_FEATURE_MIGRATION_V1:
+case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
+case VIR_DRV_FEATURE_REMOTE:
+case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
+case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
+case VIR_DRV_FEATURE_NETWORK_UPDATE_HAS_CORRECT_ORDER:
+default:
+return 0;
+}
+}
+
 static int
 chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
 {
@@ -1303,6 +1333,7 @@ static virHypervisorDriver chHypervisorDriver = {
 .connectListAllDomains = chConnectListAllDomains,   /* 7.5.0 */
 .connectListDomains = chConnectListDomains, /* 7.5.0 */
 .connectGetCapabilities = chConnectGetCapabilities, /* 7.5.0 */
+.connectSupportsFeature = chConnectSupportsFeature, /* 7.8.0 */
 .domainCreateXML = chDomainCreateXML,   /* 7.5.0 */
 .domainCreate = chDomainCreate, /* 7.5.0 */
 .domainCreateWithFlags = chDomainCreateWithFlags,   /* 7.5.0 */
-- 
2.27.0




[libvirt PATCH 06/13] ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Add domainGetVcpuPinInfo and nodeGetCPUMap callbacks to ch driver

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.h | 12 +--
 src/ch/ch_driver.c | 54 ++
 2 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index d9c9d34a19..e35777a9ec 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -23,6 +23,7 @@
 #include "ch_conf.h"
 #include "ch_monitor.h"
 #include "virchrdev.h"
+#include "vircgroup.h"
 
 /* Give up waiting for mutex after 30 seconds */
 #define CH_JOB_WAIT_TIME (1000ull * 30)
@@ -52,9 +53,16 @@ typedef struct _virCHDomainObjPrivate virCHDomainObjPrivate;
 struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
-virCHMonitor *monitor;
+virChrdevs *chrdevs;
+
+virCgroup *cgroup;
 
- virChrdevs *chrdevs;
+virCHDriver *driver;
+virCHMonitor *monitor;
+char *machineName;
+virBitmap *autoNodeset;
+virBitmap *autoCpuset;
+virChrdevs *devs;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 8ea5ce393d..62ca6c1994 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -990,6 +990,58 @@ chDomainGetMaxVcpus(virDomainPtr dom)
 return chDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | 
VIR_DOMAIN_VCPU_MAXIMUM));
 }
 
+static int
+chDomainGetVcpuPinInfo(virDomain *dom,
+   int ncpumaps,
+   unsigned char *cpumaps,
+   int maplen,
+   unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+bool live;
+int ret = -1;
+g_autoptr(virBitmap) hostcpus = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (!(hostcpus = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+
+if (live)
+autoCpuset = CH_DOMAIN_PRIVATE(vm)->autoCpuset;
+
+ret = virDomainDefGetVcpuPinInfoHelper(def, maplen, ncpumaps, cpumaps,
+   hostcpus, autoCpuset);
+cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chNodeGetCPUMap(virConnectPtr conn,
+  unsigned char **cpumap,
+  unsigned int *online,
+  unsigned int flags)
+{
+if (virNodeGetCPUMapEnsureACL(conn) < 0)
+return -1;
+
+return virHostCPUGetMap(cpumap, online, flags);
+}
+
+
 static int
 chDomainHelperGetVcpus(virDomainObj *vm,
virVcpuInfoPtr info,
@@ -1126,6 +1178,8 @@ static virHypervisorDriver chHypervisorDriver = {
 .domainGetVcpus = chDomainGetVcpus, /* 7.9.0 */
 .domainGetVcpusFlags = chDomainGetVcpusFlags,   /* 7.9.0 */
 .domainGetMaxVcpus = chDomainGetMaxVcpus,   /* 7.9.0 */
+.domainGetVcpuPinInfo = chDomainGetVcpuPinInfo, /* 7.9.0 */
+.nodeGetCPUMap = chNodeGetCPUMap,   /* 7.9.0 */
 };
 
 static virConnectDriver chConnectDriver = {
-- 
2.27.0




[libvirt PATCH 11/13] ch_driver: add numatune callbacks for CH driver

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 278 +
 1 file changed, 278 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 9ad23c1710..97dfda85e1 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -43,6 +43,7 @@
 #include "viruri.h"
 #include "virutil.h"
 #include "viruuid.h"
+#include "virnuma.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -1320,6 +1321,281 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+#define CH_NB_NUMA_PARAM 2
+
+static int
+chDomainGetNumaParameters(virDomainPtr dom,
+  virTypedParameterPtr params,
+  int *nparams,
+  unsigned int flags)
+{
+size_t i;
+virDomainObj *vm = NULL;
+virDomainNumatuneMemMode tmpmode = VIR_DOMAIN_NUMATUNE_MEM_STRICT;
+virCHDomainObjPrivate *priv;
+g_autofree char *nodeset = NULL;
+int ret = -1;
+virDomainDef *def = NULL;
+bool live = false;
+virBitmap *autoNodeset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (!(vm = virCHDomainObjFromDomain(dom)))
+return -1;
+priv = vm->privateData;
+
+if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live)
+autoNodeset = priv->autoNodeset;
+
+if ((*nparams) == 0) {
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+goto cleanup;
+}
+
+for (i = 0; i < CH_NB_NUMA_PARAM && i < *nparams; i++) {
+virMemoryParameterPtr param = ¶ms[i];
+
+switch (i) {
+case 0: /* fill numa mode here */
+ignore_value(virDomainNumatuneGetMode(def->numa, -1, &tmpmode));
+
+if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
+VIR_TYPED_PARAM_INT, tmpmode) < 0)
+goto cleanup;
+
+break;
+
+case 1: /* fill numa nodeset here */
+nodeset = virDomainNumatuneFormatNodeset(def->numa, autoNodeset, 
-1);
+
+if (!nodeset ||
+virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
+VIR_TYPED_PARAM_STRING, nodeset) < 0)
+goto cleanup;
+
+nodeset = NULL;
+break;
+
+/* coverity[dead_error_begin] */
+default:
+break;
+/* should not hit here */
+}
+}
+
+if (*nparams > CH_NB_NUMA_PARAM)
+*nparams = CH_NB_NUMA_PARAM;
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainSetNumaParamsLive(virDomainObj *vm,
+  virBitmap *nodeset)
+{
+virCgroup *cgroup_temp = NULL;
+virCHDomainObjPrivate *priv = vm->privateData;
+g_autofree char *nodeset_str = NULL;
+virDomainNumatuneMemMode mode;
+size_t i = 0;
+int ret = -1;
+
+if (virDomainNumatuneGetMode(vm->def->numa, -1, &mode) == 0 &&
+mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("change of nodeset for running domain "
+ "requires strict numa mode"));
+goto cleanup;
+}
+
+if (!virNumaNodesetIsAvailable(nodeset))
+goto cleanup;
+
+/* Ensure the cpuset string is formatted before passing to cgroup */
+if (!(nodeset_str = virBitmapFormat(nodeset)))
+goto cleanup;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+goto cleanup;
+virCgroupFree(cgroup_temp);
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def); i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (!vcpu->online)
+continue;
+
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_VCPU, i,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
+goto cleanup;
+virCgroupFree(cgroup_temp);
+}
+
+for (i = 0; i < vm->def->niothreadids; i++) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+   vm->def->iothreadids[i]->iothread_id,
+   false, &cgroup_temp) < 0 ||
+virCgroupSetCpusetMems(cgroup_temp, nodeset_str) &

[libvirt PATCH 07/13] ch_monitor: Get nicindexes in prep for cgroup mgmt

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen Paladugu 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_conf.h|  5 +++
 src/ch/ch_domain.c  | 26 +-
 src/ch/ch_domain.h  |  4 +--
 src/ch/ch_driver.c  |  4 ++-
 src/ch/ch_monitor.c | 85 +
 src/ch/ch_monitor.h | 14 +++-
 src/ch/ch_process.c |  6 +++-
 src/ch/meson.build  |  1 +
 8 files changed, 132 insertions(+), 13 deletions(-)

diff --git a/src/ch/ch_conf.h b/src/ch/ch_conf.h
index 37c36d9a09..49f286f97a 100644
--- a/src/ch/ch_conf.h
+++ b/src/ch/ch_conf.h
@@ -44,6 +44,11 @@ struct _virCHDriver
 {
 virMutex lock;
 
+bool privileged;
+
+/* Embedded Mode: Not yet supported */
+char *embeddedRoot;
+
 /* Require lock to get a reference on the object,
  * lockless access thereafter */
 virCaps *caps;
diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index c0b0b1005a..e1030800aa 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -21,10 +21,12 @@
 #include 
 
 #include "ch_domain.h"
+#include "domain_driver.h"
 #include "viralloc.h"
 #include "virchrdev.h"
 #include "virlog.h"
 #include "virtime.h"
+#include "virsystemd.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
 
@@ -136,7 +138,7 @@ virCHDomainObjEndJob(virDomainObj *obj)
 }
 
 static void *
-virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
+virCHDomainObjPrivateAlloc(void *opaque)
 {
 virCHDomainObjPrivate *priv;
 
@@ -152,6 +154,7 @@ virCHDomainObjPrivateAlloc(void *opaque G_GNUC_UNUSED)
 g_free(priv);
 return NULL;
 }
+priv->driver = opaque;
 
 return priv;
 }
@@ -363,3 +366,24 @@ virCHDomainHasVcpuPids(virDomainObj *vm)
 
 return false;
 }
+
+char *virCHDomainGetMachineName(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = CH_DOMAIN_PRIVATE(vm);
+virCHDriver *driver = priv->driver;
+char *ret = NULL;
+
+if (vm->pid > 0) {
+ret = virSystemdGetMachineNameByPID(vm->pid);
+if (!ret)
+virResetLastError();
+}
+
+if (!ret)
+ret = virDomainDriverGenerateMachineName("ch",
+ driver->embeddedRoot,
+ vm->def->id, vm->def->name,
+ driver->privileged);
+
+return ret;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index e35777a9ec..3ac3421015 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -54,9 +54,7 @@ struct _virCHDomainObjPrivate {
 struct virCHDomainJobObj job;
 
 virChrdevs *chrdevs;
-
 virCgroup *cgroup;
-
 virCHDriver *driver;
 virCHMonitor *monitor;
 char *machineName;
@@ -94,3 +92,5 @@ virCHDomainObjEndJob(virDomainObj *obj);
 int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
 pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
 bool virCHDomainHasVcpuPids(virDomainObj *vm);
+
+char *virCHDomainGetMachineName(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 62ca6c1994..ca854da123 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -944,7 +944,9 @@ static int chStateInitialize(bool privileged,
 goto cleanup;
 }
 
-ret = VIR_DRV_STATE_INIT_COMPLETE;
+ch_driver->privileged = privileged;
+
+return VIR_DRV_STATE_INIT_COMPLETE;
 
  cleanup:
 if (ret != VIR_DRV_STATE_INIT_COMPLETE)
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 691d1ce64b..c0ae031200 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -228,7 +228,8 @@ virCHMonitorBuildDisksJson(virJSONValue *content, 
virDomainDef *vmdef)
 }
 
 static int
-virCHMonitorBuildNetJson(virJSONValue *nets, virDomainNetDef *netdef)
+virCHMonitorBuildNetJson(virJSONValue *nets, virDomainNetDef *netdef,
+size_t *nnicindexes, int **nicindexes)
 {
 virDomainNetType netType = virDomainNetGetActualType(netdef);
 char macaddr[VIR_MAC_STRING_BUFLEN];
@@ -263,6 +264,18 @@ virCHMonitorBuildNetJson(virJSONValue *nets, 
virDomainNetDef *netdef)
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("ethernet type supports a single guest ip"));
 }
+
+/* network and bridge use a tap device, and direct uses a
+ * macvtap device
+ */
+if (nicindexes && nnicindexes && netdef->ifname) {
+int nicindex = 0;
+if (virNetDevGetIndex(netdef->ifname, &nicindex) < 0)
+return -1;
+else
+VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex);
+}
+
 break;
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
 if ((virDomainChrType)netdef->data.vhostuser->type != 
VIR_DOMAIN_CHR_TYPE_UNIX) {
@@ -33

[libvirt PATCH 12/13] ch_process: Setup emulator and iothread settings

2021-10-22 Thread Praveen K Paladugu
using virCHProcessSetupPid

Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_monitor.c | 60 ++
 src/ch/ch_monitor.h |  2 ++
 src/ch/ch_process.c | 78 +++--
 3 files changed, 138 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 095779cb3f..924d510a2f 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -920,3 +920,63 @@ virCHMonitorResumeVM(virCHMonitor *mon)
 {
 return virCHMonitorPutNoContent(mon, URL_VM_RESUME);
 }
+
+/**
+ * virCHMonitorGetIOThreads:
+ * @mon: Pointer to the monitor
+ * @iothreads: Location to return array of IOThreadInfo data
+ *
+ * Retrieve the list of iothreads defined/running for the machine
+ *
+ * Returns count of IOThreadInfo structures on success
+ *-1 on error.
+ */
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads)
+{
+size_t nthreads = 0, niothreads = 0;
+int thd_index;
+virDomainIOThreadInfo **iothreadinfolist = NULL, *iothreadinfo = NULL;
+
+*iothreads = NULL;
+nthreads = virCHMonitorRefreshThreadInfo(mon);
+
+iothreadinfolist = g_new0(virDomainIOThreadInfo*, nthreads);
+
+for (thd_index = 0; thd_index < nthreads; thd_index++) {
+virBitmap *map = NULL;
+if (mon->threads[thd_index].type == virCHThreadTypeIO) {
+iothreadinfo = g_new0(virDomainIOThreadInfo, 1);
+
+iothreadinfo->iothread_id = mon->threads[thd_index].ioInfo.tid;
+
+if (!(map = virProcessGetAffinity(iothreadinfo->iothread_id)))
+goto cleanup;
+
+if (virBitmapToData(map, &(iothreadinfo->cpumap),
+&(iothreadinfo->cpumaplen)) < 0) {
+virBitmapFree(map);
+goto cleanup;
+}
+virBitmapFree(map);
+//Append to iothreadinfolist
+iothreadinfolist[niothreads] = iothreadinfo;
+niothreads++;
+}
+}
+VIR_DELETE_ELEMENT_INPLACE(iothreadinfolist,
+   niothreads, nthreads);
+*iothreads = iothreadinfolist;
+VIR_DEBUG("niothreads = %ld", niothreads);
+return niothreads;
+
+cleanup:
+if (iothreadinfolist) {
+for (thd_index = 0; thd_index < niothreads; thd_index++)
+VIR_FREE(iothreadinfolist[thd_index]);
+VIR_FREE(iothreadinfolist);
+}
+if (iothreadinfo)
+VIR_FREE(iothreadinfo);
+return -1;
+}
diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h
index f8c3fa75e8..98edb0faf9 100644
--- a/src/ch/ch_monitor.h
+++ b/src/ch/ch_monitor.h
@@ -118,3 +118,5 @@ int virCHMonitorGetCPUInfo(virCHMonitor *mon,
size_t maxvcpus);
 size_t virCHMonitorGetThreadInfo(virCHMonitor *mon, bool refresh,
  virCHMonitorThreadInfo **threads);
+int virCHMonitorGetIOThreads(virCHMonitor *mon,
+virDomainIOThreadInfo ***iothreads);
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 8dce737adb..25c2910f9c 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -41,7 +41,6 @@ VIR_LOG_INIT("ch.ch_process");
 #define START_VM_POSTFIX ": starting up vm\n"
 
 
-
 static virCHMonitor *
 virCHProcessConnectMonitor(virCHDriver *driver,
virDomainObj *vm)
@@ -131,7 +130,6 @@ virCHProcessUpdateInfo(virDomainObj *vm)
 virCHProcessUpdateConsole(vm, info);
 
 virJSONValueFree(info);
-
 return 0;
 }
 
@@ -313,6 +311,74 @@ virCHProcessSetupPid(virDomainObj *vm,
 return ret;
 }
 
+static int
+virCHProcessSetupIOThread(virDomainObj *vm,
+ virDomainIOThreadInfo *iothread)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+return virCHProcessSetupPid(vm, iothread->iothread_id,
+   VIR_CGROUP_THREAD_IOTHREAD,
+   iothread->iothread_id,
+   priv->autoCpuset, // This should be updated 
when CLH supports accepting
+ // iothread settings from input domain 
definition
+   vm->def->cputune.iothread_period,
+   vm->def->cputune.iothread_quota,
+   NULL); // CLH doesn't allow choosing a 
scheduler for iothreads.
+}
+
+static int
+virCHProcessSetupIOThreads(virDomainObj *vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+virDomainIOThreadInfo **iothreads = NULL;
+size_t i;
+size_t  niothreads;
+
+niothreads = virCHMonitorGetIOThreads(priv->monitor, &iothreads);
+for (i = 0; i < niothreads; i++) {
+VIR_DEBUG("IOThread index = %ld , tid = %d", i, 
iothreads[i]->iothread_id);
+ 

[libvirt PATCH 13/13] ch_driver: emulator threadinfo & pinning callbacks

2021-10-22 Thread Praveen K Paladugu
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_driver.c | 154 +
 1 file changed, 154 insertions(+)

diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 97dfda85e1..786e2292a5 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -1321,6 +1321,158 @@ chDomainPinVcpu(virDomainPtr dom,
   VIR_DOMAIN_AFFECT_LIVE);
 }
 
+
+
+static int
+chDomainGetEmulatorPinInfo(virDomainPtr dom,
+ unsigned char *cpumaps,
+ int maplen,
+ unsigned int flags)
+{
+virDomainObj *vm = NULL;
+virDomainDef *def;
+virCHDomainObjPrivate *priv;
+bool live;
+int ret = -1;
+virBitmap *cpumask = NULL;
+g_autoptr(virBitmap) bitmap = NULL;
+virBitmap *autoCpuset = NULL;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDefState(vm, flags, &live)))
+goto cleanup;
+
+if (live) {
+priv = vm->privateData;
+autoCpuset = priv->autoCpuset;
+}
+if (def->cputune.emulatorpin) {
+cpumask = def->cputune.emulatorpin;
+} else if (def->cpumask) {
+cpumask = def->cpumask;
+} else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
+   autoCpuset) {
+cpumask = autoCpuset;
+} else {
+if (!(bitmap = virHostCPUGetAvailableCPUsBitmap()))
+goto cleanup;
+cpumask = bitmap;
+}
+
+virBitmapToDataBuf(cpumask, cpumaps, maplen);
+
+ret = 1;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainPinEmulator(virDomainPtr dom,
+  unsigned char *cpumap,
+  int maplen,
+  unsigned int flags)
+{
+virCHDriver *driver = dom->conn->privateData;
+virDomainObj *vm;
+virCgroup *cgroup_emulator = NULL;
+virDomainDef *def;
+virDomainDef *persistentDef;
+int ret = -1;
+virCHDomainObjPrivate *priv;
+virBitmap *pcpumap = NULL;
+g_autoptr(virCHDriverConfig) cfg = NULL;
+g_autofree char *str = NULL;
+virTypedParameterPtr eventParams = NULL;
+int eventNparams = 0;
+int eventMaxparams = 0;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG, -1);
+
+cfg = virCHDriverGetConfig(driver);
+
+if (!(vm = chDomObjFromDomain(dom)))
+goto cleanup;
+
+if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (virCHDomainObjBeginJob(vm, CH_JOB_MODIFY) < 0)
+goto cleanup;
+
+if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+goto endjob;
+
+priv = vm->privateData;
+
+if (!(pcpumap = virBitmapNewData(cpumap, maplen)))
+goto endjob;
+
+if (virBitmapIsAllClear(pcpumap)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Empty cpu list for pinning"));
+goto endjob;
+}
+
+if (def) {
+if (virCgroupHasController(priv->cgroup, 
VIR_CGROUP_CONTROLLER_CPUSET)) {
+if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR,
+   0, false, &cgroup_emulator) < 0)
+goto endjob;
+
+if (chSetupCgroupCpusetCpus(cgroup_emulator, pcpumap) < 0) {
+virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+   _("failed to set cpuset.cpus in cgroup"
+ " for emulator threads"));
+goto endjob;
+}
+}
+
+if (virProcessSetAffinity(vm->pid, pcpumap, false) < 0)
+goto endjob;
+
+virBitmapFree(def->cputune.emulatorpin);
+def->cputune.emulatorpin = NULL;
+
+if (!(def->cputune.emulatorpin = virBitmapNewCopy(pcpumap)))
+goto endjob;
+
+if (virDomainObjSave(vm, driver->xmlopt, cfg->stateDir) < 0)
+goto endjob;
+
+str = virBitmapFormat(pcpumap);
+if (virTypedParamsAddString(&eventParams, &eventNparams,
+&eventMaxparams,
+VIR_DOMAIN_TUNABLE_CPU_EMULATORPIN,
+str) < 0)
+goto endjob;
+
+}
+
+
+ret = 0;
+
+endjob:
+virCHDomainObjEndJob(vm);
+
+cleanup:
+if (cgroup_emulator)
+virCgroupFree(cgroup_emulator);
+virBitmapFree(pcpumap);
+virDomainObjEndAPI(&vm);
+return ret

[libvirt PATCH 08/13] ch_cgroup: methods for cgroup mgmt in ch driver

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 po/POTFILES.in  |   1 +
 src/ch/ch_cgroup.c  | 457 
 src/ch/ch_cgroup.h  |  45 +
 src/ch/ch_conf.c|   2 +
 src/ch/ch_conf.h|   4 +-
 src/ch/ch_domain.c  |  33 
 src/ch/ch_domain.h  |   3 +-
 src/ch/ch_monitor.c | 125 ++--
 src/ch/ch_monitor.h |  54 +-
 src/ch/ch_process.c | 288 +++-
 src/ch/ch_process.h |   3 +
 src/ch/meson.build  |   2 +
 12 files changed, 991 insertions(+), 26 deletions(-)
 create mode 100644 src/ch/ch_cgroup.c
 create mode 100644 src/ch/ch_cgroup.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index b554cf08ca..3a8db501bc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,6 +19,7 @@
 @SRCDIR@src/bhyve/bhyve_parse_command.c
 @SRCDIR@src/bhyve/bhyve_process.c
 @SRCDIR@src/ch/ch_conf.c
+@SRCDIR@src/ch/ch_cgroup.c
 @SRCDIR@src/ch/ch_domain.c
 @SRCDIR@src/ch/ch_driver.c
 @SRCDIR@src/ch/ch_monitor.c
diff --git a/src/ch/ch_cgroup.c b/src/ch/ch_cgroup.c
new file mode 100644
index 00..6be2184cf1
--- /dev/null
+++ b/src/ch/ch_cgroup.c
@@ -0,0 +1,457 @@
+/*
+ * ch_cgroup.c: CH cgroup management
+ *
+ * Copyright Microsoft Corp. 2020-2021
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "ch_cgroup.h"
+#include "ch_domain.h"
+#include "ch_process.h"
+#include "vircgroup.h"
+#include "virlog.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "domain_audit.h"
+#include "domain_cgroup.h"
+#include "virscsi.h"
+#include "virstring.h"
+#include "virfile.h"
+#include "virtypedparam.h"
+#include "virnuma.h"
+#include "virdevmapper.h"
+#include "virutil.h"
+
+#define VIR_FROM_THIS VIR_FROM_CH
+
+VIR_LOG_INIT("ch.ch_cgroup");
+
+static int
+chSetupBlkioCgroup(virDomainObj * vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+
+if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_BLKIO)) {
+if (vm->def->blkio.weight || vm->def->blkio.ndevices) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Block I/O tuning is not available on this 
host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupBlkio(priv->cgroup, vm->def->blkio);
+}
+
+
+static int
+chSetupMemoryCgroup(virDomainObj * vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+
+if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_MEMORY)) {
+if (virMemoryLimitIsSet(vm->def->mem.hard_limit) ||
+virMemoryLimitIsSet(vm->def->mem.soft_limit) ||
+virMemoryLimitIsSet(vm->def->mem.swap_hard_limit)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("Memory cgroup is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+return virDomainCgroupSetupMemtune(priv->cgroup, vm->def->mem);
+}
+
+static int
+chSetupCpusetCgroup(virDomainObj * vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+
+if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET))
+return 0;
+
+if (virCgroupSetCpusetMemoryMigrate(priv->cgroup, true) < 0)
+return -1;
+
+return 0;
+}
+
+
+static int
+chSetupCpuCgroup(virDomainObj * vm)
+{
+virCHDomainObjPrivate *priv = vm->privateData;
+
+if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) {
+if (vm->def->cputune.sharesSpecified) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("CPU tuning is not available on this host"));
+return -1;
+} else {
+return 0;
+}
+}
+
+if (vm->def->cputune.sharesSpecified) {
+
+if (virCgroupSetCpuShares(priv->cgroup, vm->def->cputune.shares) < 0)
+return -1;
+
+}
+
+return 0;
+}
+
+
+static int
+chInitC

[libvirt PATCH 05/13] ch_driver, ch_domain: vcpu info getter callbacks

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c |  25 
 src/ch/ch_domain.h |   4 ++
 src/ch/ch_driver.c | 138 +
 3 files changed, 167 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index fedde4581b..c0b0b1005a 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -338,3 +338,28 @@ virCHDomainGetMonitor(virDomainObj *vm)
 {
 return CH_DOMAIN_PRIVATE(vm)->monitor;
 }
+
+pid_t
+virCHDomainGetVcpuPid(virDomainObj *vm,
+ unsigned int vcpuid)
+{
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, vcpuid);
+return CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid;
+}
+
+bool
+virCHDomainHasVcpuPids(virDomainObj *vm)
+{
+size_t i;
+size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
+virDomainVcpuDef *vcpu;
+
+for (i = 0; i < maxvcpus; i++) {
+vcpu = virDomainDefGetVcpu(vm->def, i);
+
+if (CH_DOMAIN_VCPU_PRIVATE(vcpu)->tid > 0)
+return true;
+}
+
+return false;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 75b9933130..d9c9d34a19 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -82,3 +82,7 @@ virCHDomainObjBeginJob(virDomainObj *obj, enum virCHDomainJob 
job)
 
 void
 virCHDomainObjEndJob(virDomainObj *obj);
+
+int virCHDomainRefreshVcpuInfo(virDomainObj *vm);
+pid_t virCHDomainGetVcpuPid(virDomainObj *vm, unsigned int vcpuid);
+bool virCHDomainHasVcpuPids(virDomainObj *vm);
diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c
index 1824d2fd16..8ea5ce393d 100644
--- a/src/ch/ch_driver.c
+++ b/src/ch/ch_driver.c
@@ -952,6 +952,141 @@ static int chStateInitialize(bool privileged,
 return ret;
 }
 
+static int
+chDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
+virDomainObj *vm;
+virDomainDef *def;
+int ret = -1;
+
+virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+  VIR_DOMAIN_AFFECT_CONFIG |
+  VIR_DOMAIN_VCPU_MAXIMUM |
+  VIR_DOMAIN_VCPU_GUEST, -1);
+
+if (!(vm = chDomObjFromDomain(dom)))
+return -1;
+
+if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
+goto cleanup;
+
+if (!(def = virDomainObjGetOneDef(vm, flags)))
+goto cleanup;
+
+if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
+ret = virDomainDefGetVcpusMax(def);
+else
+ret = virDomainDefGetVcpus(def);
+
+
+cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
+static int
+chDomainGetMaxVcpus(virDomainPtr dom)
+{
+return chDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE | 
VIR_DOMAIN_VCPU_MAXIMUM));
+}
+
+static int
+chDomainHelperGetVcpus(virDomainObj *vm,
+   virVcpuInfoPtr info,
+   unsigned long long *cpuwait,
+   int maxinfo,
+   unsigned char *cpumaps,
+   int maplen)
+{
+size_t ncpuinfo = 0;
+size_t i;
+
+if (maxinfo == 0)
+return 0;
+
+if (!virCHDomainHasVcpuPids(vm)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   "%s", _("cpu affinity is not supported"));
+return -1;
+}
+
+if (info)
+memset(info, 0, sizeof(*info) * maxinfo);
+
+if (cpumaps)
+memset(cpumaps, 0, sizeof(*cpumaps) * maxinfo);
+
+for (i = 0; i < virDomainDefGetVcpusMax(vm->def) && ncpuinfo < maxinfo; 
i++) {
+virDomainVcpuDef *vcpu = virDomainDefGetVcpu(vm->def, i);
+pid_t vcpupid = virCHDomainGetVcpuPid(vm, i);
+virVcpuInfoPtr vcpuinfo = info + ncpuinfo;
+
+if (!vcpu->online)
+continue;
+
+if (info) {
+vcpuinfo->number = i;
+vcpuinfo->state = VIR_VCPU_RUNNING;
+if (virProcessGetStatInfo(&vcpuinfo->cpuTime,
+  &vcpuinfo->cpu, NULL,
+  vm->pid, vcpupid) < 0) {
+virReportSystemError(errno, "%s",
+ _("cannot get vCPU placement & pCPU 
time"));
+return -1;
+}
+}
+
+if (cpumaps) {
+unsigned char *cpumap = VIR_GET_CPUMAP(cpumaps, maplen, ncpuinfo);
+virBitmap *map = NULL;
+
+if (!(map = virProcessGetAffinity(vcpupid)))
+return -1;
+
+virBitmapToDataBuf(map, cpumap, maplen);
+virBitmapFree(map);
+}
+
+if (cpuwait) {
+if (virProcessGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) 
< 0)
+return -1;
+}
+
+ncpuinfo++;
+}
+
+return ncpuinfo;
+}
+
+static int
+chDomainGetVcpus(virDomainPtr dom,
+   virVcpuInfoPtr info,
+   int maxinfo,
+

[libvirt PATCH 02/13] ch: Explicitly link to virt_util_lib

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

link to virt_util_lib while building ch driver.

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/meson.build | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/ch/meson.build b/src/ch/meson.build
index e34974d56c..5c6cab2a9f 100644
--- a/src/ch/meson.build
+++ b/src/ch/meson.build
@@ -30,6 +30,9 @@ if conf.has('WITH_CH')
 include_directories: [
   conf_inc_dir,
 ],
+link_with: [
+  virt_util_lib,
+]
   )
 
   virt_modules += {
-- 
2.27.0




[libvirt PATCH 03/13] ch_domain: add virCHDomainGetMonitor helper method

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 6 ++
 src/ch/ch_domain.h | 5 +
 2 files changed, 11 insertions(+)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index 9d32d8669a..ae79b47253 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -292,3 +292,9 @@ virDomainDefParserConfig virCHDriverDomainDefParserConfig = 
{
 .domainPostParseCallback = virCHDomainDefPostParse,
 .deviceValidateCallback = chValidateDomainDeviceDef,
 };
+
+virCHMonitor *
+virCHDomainGetMonitor(virDomainObj *vm)
+{
+return CH_DOMAIN_PRIVATE(vm)->monitor;
+}
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 61b34b0467..04d19398b4 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -57,6 +57,11 @@ struct _virCHDomainObjPrivate {
  virChrdevs *chrdevs;
 };
 
+#define CH_DOMAIN_PRIVATE(vm) \
+((virCHDomainObjPrivate *) (vm)->privateData)
+
+virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH 00/13] cgroup and thread management in ch driver.

2021-10-22 Thread Praveen K Paladugu
This patchset adds support for cgroup management of ch threads. This version
correctly manages cgroups for vcpu and emulator threads created by ch. cgroup
management for iothreads is not yet supported.

Along with cgroup management, this patchset also enables support for pinning
vcpu and emulator threads to selected host cpus.

Praveen K Paladugu (2):
  ch_process: Setup emulator and iothread settings
  ch_driver: emulator threadinfo & pinning callbacks

Vineeth Pillai (11):
  util: Helper functions to get process info
  ch: Explicitly link to virt_util_lib
  ch_domain: add virCHDomainGetMonitor helper method
  ch_domain: add methods to manage private vcpu data
  ch_driver,ch_domain: vcpu info getter callbacks
  ch_driver: domainGetVcpuPinInfo and nodeGetCPUMap
  ch_monitor: Get nicindexes in prep for cgroup mgmt
  ch_cgroup: methods for cgroup mgmt in ch driver
  ch_driver,ch_domain: vcpupin callback in ch driver
  ch_driver: enable typed param string for numatune
  ch_driver: add numatune callbacks for CH driver

 po/POTFILES.in|   1 +
 src/ch/ch_cgroup.c| 457 
 src/ch/ch_cgroup.h|  45 +++
 src/ch/ch_conf.c  |   2 +
 src/ch/ch_conf.h  |   9 +-
 src/ch/ch_domain.c| 170 -
 src/ch/ch_domain.h|  32 +-
 src/ch/ch_driver.c| 810 +-
 src/ch/ch_monitor.c   | 254 -
 src/ch/ch_monitor.h   |  60 +++-
 src/ch/ch_process.c   | 368 ++-
 src/ch/ch_process.h   |   3 +
 src/ch/meson.build|   6 +
 src/util/virprocess.c | 136 +++
 src/util/virprocess.h |   5 +
 15 files changed, 2329 insertions(+), 29 deletions(-)
 create mode 100644 src/ch/ch_cgroup.c
 create mode 100644 src/ch/ch_cgroup.h

-- 
2.27.0




[libvirt PATCH 04/13] ch_domain: add methods to manage private vcpu data

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/ch/ch_domain.c | 50 +-
 src/ch/ch_domain.h | 11 ++
 2 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index ae79b47253..fedde4581b 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -166,11 +166,6 @@ virCHDomainObjPrivateFree(void *data)
 g_free(priv);
 }
 
-virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
-.alloc = virCHDomainObjPrivateAlloc,
-.free = virCHDomainObjPrivateFree,
-};
-
 static int
 virCHDomainDefPostParseBasic(virDomainDef *def,
  void *opaque G_GNUC_UNUSED)
@@ -187,6 +182,45 @@ virCHDomainDefPostParseBasic(virDomainDef *def,
 return 0;
 }
 
+static virClass *virCHDomainVcpuPrivateClass;
+static void virCHDomainVcpuPrivateDispose(void *obj);
+
+static int
+virCHDomainVcpuPrivateOnceInit(void)
+{
+if (!VIR_CLASS_NEW(virCHDomainVcpuPrivate, virClassForObject()))
+return -1;
+
+return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virCHDomainVcpuPrivate);
+
+static virObject *
+virCHDomainVcpuPrivateNew(void)
+{
+virCHDomainVcpuPrivate *priv;
+
+if (virCHDomainVcpuPrivateInitialize() < 0)
+return NULL;
+
+if (!(priv = virObjectNew(virCHDomainVcpuPrivateClass)))
+return NULL;
+
+return (virObject *) priv;
+}
+
+
+static void
+virCHDomainVcpuPrivateDispose(void *obj)
+{
+virCHDomainVcpuPrivate *priv = obj;
+
+priv->tid = 0;
+
+return;
+}
+
 static int
 virCHDomainDefPostParse(virDomainDef *def,
 unsigned int parseFlags G_GNUC_UNUSED,
@@ -205,6 +239,12 @@ virCHDomainDefPostParse(virDomainDef *def,
 return 0;
 }
 
+virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks = {
+.alloc = virCHDomainObjPrivateAlloc,
+.free = virCHDomainObjPrivateFree,
+.vcpuNew = virCHDomainVcpuPrivateNew,
+};
+
 static int
 chValidateDomainDeviceDef(const virDomainDeviceDef *dev,
   const virDomainDef *def G_GNUC_UNUSED,
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 04d19398b4..75b9933130 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -62,6 +62,17 @@ struct _virCHDomainObjPrivate {
 
 virCHMonitor *virCHDomainGetMonitor(virDomainObj *vm);
 
+typedef struct _virCHDomainVcpuPrivate virCHDomainVcpuPrivate;
+struct _virCHDomainVcpuPrivate {
+virObject parent;
+
+pid_t tid; /* vcpu thread id */
+virTristateBool halted;
+};
+
+#define CH_DOMAIN_VCPU_PRIVATE(vcpu) \
+((virCHDomainVcpuPrivate *) (vcpu)->privateData)
+
 extern virDomainXMLPrivateDataCallbacks virCHDriverPrivateDataCallbacks;
 extern virDomainDefParserConfig virCHDriverDomainDefParserConfig;
 
-- 
2.27.0




[libvirt PATCH 01/13] util: Helper functions to get process info

2021-10-22 Thread Praveen K Paladugu
From: Vineeth Pillai 

These helper methods are used to capture vcpu information
in ch driver.

Signed-off-by: Vineeth Pillai 
Signed-off-by: Praveen K Paladugu 
---
 src/util/virprocess.c | 136 ++
 src/util/virprocess.h |   5 ++
 2 files changed, 141 insertions(+)

diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 6de3f36f52..0164d70df6 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -1721,3 +1721,139 @@ virProcessSetScheduler(pid_t pid G_GNUC_UNUSED,
 }
 
 #endif /* !WITH_SCHED_SETSCHEDULER */
+
+/*
+TODO: This method was cloned from qemuGetProcessInfo in src/qemu/qemu_driver.c.
+Need to refactor qemu driver to use this shared function.
+*/
+int
+virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss,
+   pid_t pid, pid_t tid)
+{
+g_autofree char *proc = NULL;
+FILE *pidinfo;
+unsigned long long usertime = 0, systime = 0;
+long rss = 0;
+int cpu = 0;
+
+/* In general, we cannot assume pid_t fits in int; but /proc parsing
+ * is specific to Linux where int works fine.  */
+if (tid)
+proc = g_strdup_printf("/proc/%d/task/%d/stat", (int)pid, tid);
+else
+proc = g_strdup_printf("/proc/%d/stat", (int)pid);
+if (!proc)
+return -1;
+
+pidinfo = fopen(proc, "r");
+
+/* See 'man proc' for information about what all these fields are. We're
+ * only interested in a very few of them */
+if (!pidinfo ||
+fscanf(pidinfo,
+   /* pid -> stime */
+   "%*d (%*[^)]) %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu 
%llu"
+   /* cutime -> endcode */
+   "%*d %*d %*d %*d %*d %*d %*u %*u %ld %*u %*u %*u"
+   /* startstack -> processor */
+   "%*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*d %d",
+   &usertime, &systime, &rss, &cpu) != 4) {
+VIR_WARN("cannot parse process status data");
+}
+
+/* We got jiffies
+ * We want nanoseconds
+ * _SC_CLK_TCK is jiffies per second
+ * So calculate thus
+ */
+if (cpuTime)
+*cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime)
+/ (unsigned long long)sysconf(_SC_CLK_TCK);
+if (lastCpu)
+*lastCpu = cpu;
+
+if (vm_rss)
+*vm_rss = rss * virGetSystemPageSizeKB();
+
+
+VIR_DEBUG("Got status for %d/%d user=%llu sys=%llu cpu=%d rss=%ld",
+  (int)pid, tid, usertime, systime, cpu, rss);
+
+VIR_FORCE_FCLOSE(pidinfo);
+
+return 0;
+}
+/*
+TODO: This method was cloned from qemuGetSchedInfo in src/qemu/qemu_driver.c.
+Need to refactor qemu driver to use this shared function.
+*/
+int virProcessGetSchedInfo(unsigned long long *cpuWait, pid_t pid, pid_t tid)
+{
+g_autofree char *proc = NULL;
+g_autofree char *data = NULL;
+char **lines = NULL;
+size_t i;
+int ret = -1;
+double val;
+
+*cpuWait = 0;
+
+/* In general, we cannot assume pid_t fits in int; but /proc parsing
+ * is specific to Linux where int works fine.  */
+if (tid)
+proc = g_strdup_printf("/proc/%d/task/%d/sched", (int)pid, (int)tid);
+else
+proc = g_strdup_printf("/proc/%d/sched", (int)pid);
+if (!proc)
+goto cleanup;
+ret = -1;
+
+/* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */
+if (access(proc, R_OK) < 0) {
+ret = 0;
+goto cleanup;
+}
+
+if (virFileReadAll(proc, (1<<16), &data) < 0)
+goto cleanup;
+
+lines = g_strsplit(data, "\n", 0);
+if (!lines)
+goto cleanup;
+
+for (i = 0; lines[i] != NULL; i++) {
+const char *line = lines[i];
+
+/* Needs CONFIG_SCHEDSTATS. The second check
+ * is the old name the kernel used in past */
+if (STRPREFIX(line, "se.statistics.wait_sum") ||
+STRPREFIX(line, "se.wait_sum")) {
+line = strchr(line, ':');
+if (!line) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Missing separator in sched info '%s'"),
+   lines[i]);
+goto cleanup;
+}
+line++;
+while (*line == ' ')
+line++;
+
+if (virStrToDouble(line, NULL, &val) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Unable to parse sched info value '%s'"),
+   line);
+goto cleanup;
+}
+
+*cpuWait = (unsigned long long)(val * 100);
+break;
+}
+}
+
+ret = 0;
+
+ cleanup:
+g_strfreev(lines);
+return ret;

Re: [PATCH v1] tools: add virt-host-validate-ch for ch driver

2021-10-12 Thread Praveen K Paladugu




On 10/12/2021 10:32 AM, Michal Prívozník wrote:

On 10/7/21 11:49 PM, Praveen K Paladugu wrote:

Signed-off-by: Wei-Chen Chen 
Signed-off-by: Praveen K Paladugu 
---
  po/POTFILES.in|  1 +
  tools/meson.build |  5 +++
  tools/virt-host-validate-ch.c | 85 +++
  tools/virt-host-validate-ch.h | 24 ++
  tools/virt-host-validate.c| 12 +
  5 files changed, 127 insertions(+)
  create mode 100644 tools/virt-host-validate-ch.c
  create mode 100644 tools/virt-host-validate-ch.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index c200d7452a..b554cf08ca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -369,6 +369,7 @@
  @SRCDIR@tools/virsh.h
  @SRCDIR@tools/virt-admin.c
  @SRCDIR@tools/virt-host-validate-bhyve.c
+@SRCDIR@tools/virt-host-validate-ch.c
  @SRCDIR@tools/virt-host-validate-common.c
  @SRCDIR@tools/virt-host-validate-lxc.c
  @SRCDIR@tools/virt-host-validate-qemu.c
diff --git a/tools/meson.build b/tools/meson.build
index 2acf7b0aaf..bf0eab8b6b 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -58,6 +58,11 @@ if conf.has('WITH_HOST_VALIDATE')
'virt-host-validate-bhyve.c',
  ]
endif
+  if conf.has('WITH_CH')
+virt_host_validate_sources += [
+  'virt-host-validate-ch.c',
+]
+  endif
  
executable(

  'virt-host-validate',
diff --git a/tools/virt-host-validate-ch.c b/tools/virt-host-validate-ch.c
new file mode 100644
index 00..a6d8a01d1b
--- /dev/null
+++ b/tools/virt-host-validate-ch.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright Microsoft Corp. 2020-2021
+ *
+ * virt-host-validate-ch.c: Sanity check a CH hypervisor host


We usually put this line first and Copyright after that.


+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "virarch.h"
+#include "virbitmap.h"
+#include "virt-host-validate-ch.h"
+#include "virt-host-validate-common.h"
+
+int virHostValidateCh(void)
+{
+  int ret = 0;
+  virBitmap *flags;
+  bool hasHwVirt = false;
+  bool hasVirtFlag = false;
+  virArch arch = virArchFromHost();
+  const char *kvmhint =
+  _("Check that CPU and firmware supports virtualization "
+"and kvm module is loaded");
+


This entire function is not formatted according to our guidelines.

https://libvirt.org/coding-style.html


Will pay attention to coding style for future patches.


+  if (!(flags = virHostValidateGetCPUFlags()))
+return -1;
+
+  // Cloud-Hypervisor only supports x86_64 and aarch64


We are a bit old school and like C89 style of comments.

These are all small nits that I can fix before pushing.

Reviewed-by: Michal Privoznik 

Congratulations on your first libvirt contribution!


Thank you!!


Michal



--
Regards,
Praveen K Paladugu




[PATCH v1] tools: add virt-host-validate-ch for ch driver

2021-10-07 Thread Praveen K Paladugu
Signed-off-by: Wei-Chen Chen 
Signed-off-by: Praveen K Paladugu 
---
 po/POTFILES.in|  1 +
 tools/meson.build |  5 +++
 tools/virt-host-validate-ch.c | 85 +++
 tools/virt-host-validate-ch.h | 24 ++
 tools/virt-host-validate.c| 12 +
 5 files changed, 127 insertions(+)
 create mode 100644 tools/virt-host-validate-ch.c
 create mode 100644 tools/virt-host-validate-ch.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index c200d7452a..b554cf08ca 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -369,6 +369,7 @@
 @SRCDIR@tools/virsh.h
 @SRCDIR@tools/virt-admin.c
 @SRCDIR@tools/virt-host-validate-bhyve.c
+@SRCDIR@tools/virt-host-validate-ch.c
 @SRCDIR@tools/virt-host-validate-common.c
 @SRCDIR@tools/virt-host-validate-lxc.c
 @SRCDIR@tools/virt-host-validate-qemu.c
diff --git a/tools/meson.build b/tools/meson.build
index 2acf7b0aaf..bf0eab8b6b 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -58,6 +58,11 @@ if conf.has('WITH_HOST_VALIDATE')
   'virt-host-validate-bhyve.c',
 ]
   endif
+  if conf.has('WITH_CH')
+virt_host_validate_sources += [
+  'virt-host-validate-ch.c',
+]
+  endif
 
   executable(
 'virt-host-validate',
diff --git a/tools/virt-host-validate-ch.c b/tools/virt-host-validate-ch.c
new file mode 100644
index 00..a6d8a01d1b
--- /dev/null
+++ b/tools/virt-host-validate-ch.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright Microsoft Corp. 2020-2021
+ *
+ * virt-host-validate-ch.c: Sanity check a CH hypervisor host
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+
+#include "virarch.h"
+#include "virbitmap.h"
+#include "virt-host-validate-ch.h"
+#include "virt-host-validate-common.h"
+
+int virHostValidateCh(void)
+{
+  int ret = 0;
+  virBitmap *flags;
+  bool hasHwVirt = false;
+  bool hasVirtFlag = false;
+  virArch arch = virArchFromHost();
+  const char *kvmhint =
+  _("Check that CPU and firmware supports virtualization "
+"and kvm module is loaded");
+
+  if (!(flags = virHostValidateGetCPUFlags()))
+return -1;
+
+  // Cloud-Hypervisor only supports x86_64 and aarch64
+  switch ((int)arch) {
+case VIR_ARCH_X86_64:
+  hasVirtFlag = true;
+  kvmhint = _("Check that the 'kvm-intel' or 'kvm-amd' modules are "
+  "loaded & the BIOS has enabled virtualization");
+  if (virBitmapIsBitSet(flags, VIR_HOST_VALIDATE_CPU_FLAG_SVM) ||
+  virBitmapIsBitSet(flags, VIR_HOST_VALIDATE_CPU_FLAG_VMX))
+hasHwVirt = true;
+  break;
+case VIR_ARCH_AARCH64:
+  hasVirtFlag = true;
+  hasHwVirt = true;
+  break;
+default:
+  hasHwVirt = false;
+  break;
+  }
+
+  if (hasVirtFlag) {
+virHostMsgCheck("CH", "%s", _("for hardware virtualization"));
+if (hasHwVirt) {
+  virHostMsgPass();
+} else {
+  virHostMsgFail(VIR_HOST_VALIDATE_FAIL,
+ _("Only emulated CPUs are available, performance will be "
+   "significantly limited"));
+  ret = -1;
+}
+  }
+
+  if (hasHwVirt || !hasVirtFlag) {
+if (virHostValidateDeviceExists("CH", "/dev/kvm", VIR_HOST_VALIDATE_FAIL,
+kvmhint) < 0)
+  ret = -1;
+else if (virHostValidateDeviceAccessible(
+ "CH", "/dev/kvm", VIR_HOST_VALIDATE_FAIL,
+ _("Check /dev/kvm is world writable or you are in "
+   "a group that is allowed to access it")) < 0)
+  ret = -1;
+  }
+
+  return ret;
+}
diff --git a/tools/virt-host-validate-ch.h b/tools/virt-host-validate-ch.h
new file mode 100644
index 00..b16e7d36ab
--- /dev/null
+++ b/tools/virt-host-validate-ch.h
@@ -0,0 +1,24 @@
+/*
+ * virt-host-validate-ch.h: Sanity check a CH hypervisor host
+ *
+ * Copyright Microsoft Corp. 2020-2021
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your op

Re: Libvirt CI for running functional tests

2021-06-04 Thread Praveen K Paladugu

Erik,

Thanks for this detailed response. It answers many questions we had 
about CI for libvirt.



On 6/2/2021 3:32 AM, Erik Skultety wrote:

On Thu, May 27, 2021 at 11:17:04AM -0500, Praveen K Paladugu wrote:

Hi,

While developing cloud-hypervisor driver for libvirt, we re-fitted
cloud-hypervisor project's CI to libvirt. This CI was built on Rust and
currently supports VM boot up tests.

https://github.com/cloud-hypervisor/libvirt/tree/ch/ch_integration_tests


Hi,
so excited to hear about ^this effort - I haven't gone over the code base yet,
but nevertheless having something set up already at your side is awesome.



We are working on extending this CI to incorporate more functional tests:
Networking, Thread Pinning etc. We are curious to know if libvirt project
has any plans to setup a CI to run functional tests.

I noticed https://gitlab.com/libvirt/libvirt-ci effort which focuses on
running builds against various platforms and formats. Could you please
clarify libvirt project's plan for setting up a CI to run functional tests.



Yes, we do have plans. As you've already correctly noted, currently we only
have automated builds running in GitLab the configuration of which comes and is
maintained by the libvirt-ci project. As for the functional tests though, we're
currently fighting on 3 fronts:
 - infrastructure
 - automation machinery
 - testing framework

Without going in too much detail we're working on improving libvirt-ci project
in a way that would allow to make libvirt CI configurable for any interested
party, IOW we'd set a standard on what the machines should look like and how
libvirt expects to interact with them \wrt executing tests on them, but what
tests you run on them is up to you as long as you report them back to the
upstream libvirt pipeline (most likely gitlab).

To go to a little more detail:

Infrastructure
--
- we're planning on running the workloads in nested KVM VMs, because it's much
   easier to set up in an automated fashion, is suitable to be run on local
   developer's machines and can be thrown away afterwards

- machines will be connected to gitlab with the gitlab-runner agent
  (provided we don't decide to move to a different platform which is not likely
   even with the restriction on using public runners with the free tier)

Automation
--
- this will be handled by libvirt-ci (lcitool) which already has support for
   both container and VM workloads, we just have to shape it so that it can do
   what we want in terms of functional tests in VM workloads

Test framework
--
- there already are 2 frameworks: Avocado-VT and libvirt TCK none of which
   ultimately will be used, because they're not particulary libvirt developer
   friendly for various reasons (not the point of this email)

- we're experimenting with using the plain Avocado framework integration just
   like QEMU has already done upstream (so we'd like to stay in aligned with 
QEMU)

- the main arguments for selecting the Avocado framework are (there a few more):
 -> the native language of Avocado is Python which we already decided in
upstream libvirt to be the dominant, modern and preferred scripting
language of many users/contributors

 -> Avocado is truly language agnostic as far as tests go, so if you're
bringing an existing test suite in a different language like e.g. Bash,
that is fine Avocado can detect and execute external tests as well

 -> Avocado supports many of the new test result formats out there along
with the simple and older TAP format, so it can satisfy various needs

 -> Avocado supports parallel test executions

- as for what the initial deployment will utilize, it's impossible to think
   that we're going to port all of Avocado-VTs 17k test case (hell no!), so we'd
   start with the older test set coming from libvirt TCK which has proven to


What do you mean by "older test set" here? Could you please point me to 
some links/docs related to this test set?


If this test set has sufficient coverage for our usecase, we will 
consider pivoting to avocado suite for future test cases.



   catch serious bugs, but new tests would be written solely in Python and
   very very slowly we'd migrate the TCK test cases from Perl to Python and host
   all of it as part of the main libvirt repo

I hope that ^this gist would be enough of an answer to you :). Stay tuned for
next plans on the CI front.

Regards,
Erik



Lastly, where can we follow the adoption of Avocado Framework? Will this 
start in libvirt-ci repository?



--
Regards,
Praveen K Paladugu



Libvirt CI for running functional tests

2021-05-27 Thread Praveen K Paladugu

Hi,

While developing cloud-hypervisor driver for libvirt, we re-fitted 
cloud-hypervisor project's CI to libvirt. This CI was built on Rust and 
currently supports VM boot up tests.


https://github.com/cloud-hypervisor/libvirt/tree/ch/ch_integration_tests

We are working on extending this CI to incorporate more functional 
tests: Networking, Thread Pinning etc. We are curious to know if libvirt 
project has any plans to setup a CI to run functional tests.


I noticed https://gitlab.com/libvirt/libvirt-ci effort which focuses on 
running builds against various platforms and formats. Could you please 
clarify libvirt project's plan for setting up a CI to run functional tests.



Regards,
Praveen K Paladugu