[Libvirt-cim] [PATCH] Add support for libvirt CPU cgroup for active KVM guests

Gareth S. Bestor bestor at us.ibm.com
Mon Oct 3 09:52:10 UTC 2011


# HG changeset patch
# User Gareth S. Bestor <bestor at us.ibm.com>
# Date 1317635486 25200
# Node ID 2c9a378e141c23eae0b96b2f021adbd14cfb8ef2
# Parent  fb09136deb494008eb3aacee420ad74da7d7c294
Add support for libvirt CPU cgroup for active KVM guests
Add support for setting and retreiving the CPU cgroup setting for an active KVM guest
using libivirt scheduling parameter support. Presently this patches only supports earlier
libvirt versions' support of this feature, which only support setting these scheduling
params for *active* guests only, and uses libivrt's earlier scheduling APIs; a subsequent
patch will support both and the newer APIs (version dependent).
A guest's CPU cgroup setting it exposed via the KVM_ProcResourceAllocationSettingData.Weight
property.
Minimum, maximum, Increment and Default weights are exposed appropriately via
the respective Processor pool.
Weight for new guest can be passed in on DefineSystem[]
Weigh for existing (active) guest can be changed via ModifyResourceSettings[]
Signed-off-by: Gareth S. Bestor <bestor at us.bm.com>

diff -r fb09136deb49 -r 2c9a378e141c libxkutil/device_parsing.c
--- a/libxkutil/device_parsing.c	Tue Aug 30 08:48:36 2011 -0700
+++ b/libxkutil/device_parsing.c	Mon Oct 03 02:51:26 2011 -0700
@@ -1297,6 +1297,24 @@
 {
         int ret;
 
+        /* Change vcpu cgroup cpu_shares */
+        if (dev->dev.vcpu.weight > 0) {
+                virSchedParameter param;
+
+                strncpy(param.field, "cpu_shares", VIR_DOMAIN_SCHED_FIELD_LENGTH);
+                param.type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
+                param.value.ul = dev->dev.vcpu.weight;
+                
+                if (virDomainSetSchedulerParameters(dom, &param, 1) != 0) {
+                        CU_DEBUG("Failed to set scheduler params for domain");
+                        return 0;
+                }
+
+                CU_DEBUG("Changed %s vcpu cgroup cpu_shares to %i",
+                         virDomainGetName(dom),
+                         dev->dev.vcpu.weight);
+        }
+
         if (dev->dev.vcpu.quantity <= 0) {
                 CU_DEBUG("Unable to set VCPU count to %i",
                          dev->dev.vcpu.quantity);
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_ComputerSystem.c
--- a/src/Virt_ComputerSystem.c	Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Virt_ComputerSystem.c	Mon Oct 03 02:51:26 2011 -0700
@@ -858,6 +858,30 @@
         return 0;
 }
 
+static int kvm_scheduler_params(struct infostore_ctx *ctx,
+                                virSchedParameter **params)
+{
+        unsigned long long value;
+
+        *params = calloc(1, sizeof(virSchedParameter));
+        if (*params == NULL)
+                return -1;
+
+        value = infostore_get_u64(ctx, "weight");
+
+        if (value != 0) {
+                strncpy((*params)[0].field,
+                        "cpu_shares",
+                        VIR_DOMAIN_SCHED_FIELD_LENGTH);
+                (*params)[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
+                (*params)[0].value.ul = value;
+
+                return 1;
+        }
+
+        return 0;
+}
+
 static void set_scheduler_params(virDomainPtr dom)
 {
         struct infostore_ctx *ctx;
@@ -881,6 +905,8 @@
                 count = xen_scheduler_params(ctx, &params);
         else if (STREQC(virConnectGetType(conn), "lxc"))
                 count = lxc_scheduler_params(ctx, &params);
+        else if (STREQC(virConnectGetType(conn), "QEMU"))
+                count = kvm_scheduler_params(ctx, &params);
         else {
                 CU_DEBUG("Not setting sched params for type %s",
                          virConnectGetType(conn));
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_RASD.c
--- a/src/Virt_RASD.c	Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Virt_RASD.c	Mon Oct 03 02:51:26 2011 -0700
@@ -110,7 +110,7 @@
         virConnectPtr conn = NULL;
         virDomainPtr dom = NULL;
         struct infostore_ctx *info = NULL;
-        uint32_t weight;
+        uint32_t weight = 0;
         uint64_t limit;
         uint64_t count;
 
@@ -147,7 +147,45 @@
                 goto out;
         }
 
-        weight = (uint32_t)infostore_get_u64(info, "weight");
+        /* Currently only support CPU cgroups for running KVM guests */
+        if (domain_online(dom) && STREQC(virConnectGetType(conn), "QEMU")) {
+                char *sched;
+                int nparams;
+                unsigned int i;
+                virSchedParameter *params;
+
+                /* First find the number of scheduler params, in order malloc space for them all */
+                sched = virDomainGetSchedulerType(dom, &nparams);
+                if (sched == NULL) {
+                        CU_DEBUG("Failed to get scheduler type");
+                        goto out;
+                }
+                CU_DEBUG("domain has %d scheduler params", nparams);
+                free(sched);
+
+                /* Now retrieve all the scheduler params for this domain */
+                params = calloc(nparams, sizeof(virSchedParameter));
+                if (virDomainGetSchedulerParameters(dom, params, &nparams) != 0) {
+                        CU_DEBUG("Failed to get scheduler params for domain");
+                        goto out;
+                }
+
+                /* Look for the CPU cgroup scheduler parameter, called 'cpu_shares' */
+                for (i = 0 ; i < nparams ; i++) {
+                        CU_DEBUG("scheduler param #%d name is %s (type %d)", 
+                                 i, params[i].field, params[i].type);
+                        if (STREQ(params[i].field, "cpu_shares") && 
+                            (params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG)) {
+                                CU_DEBUG("scheduler param %s = %d",
+                                         params[i].field, params[i].value.ul);
+                                weight = (uint32_t)params[i].value.ul;
+                                break; /* Found it! */
+                        }
+                }
+                free(params);
+        }
+        else 
+                weight = (uint32_t)infostore_get_u64(info, "weight");
         limit = infostore_get_u64(info, "limit");
 
         CMSetProperty(inst, "Weight",
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_SettingsDefineCapabilities.c
--- a/src/Virt_SettingsDefineCapabilities.c	Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Virt_SettingsDefineCapabilities.c	Mon Oct 03 02:51:26 2011 -0700
@@ -410,7 +410,10 @@
         case SDC_RASD_MIN:
                 num_procs = 0;
                 limit = 1;
-                weight = MIN_XEN_WEIGHT;
+                if (STARTS_WITH(CLASSNAME(ref), "Xen"))
+                        weight = MIN_XEN_WEIGHT;
+                else if (STARTS_WITH(CLASSNAME(ref), "KVM"))
+                        weight = MIN_KVM_WEIGHT;
                 id = "Minimum";
                 break;
         case SDC_RASD_MAX:
@@ -418,19 +421,28 @@
                 if (!ret)
                     goto out;
                 limit = 0;
-                weight = MAX_XEN_WEIGHT;
+                if (STARTS_WITH(CLASSNAME(ref), "Xen"))
+                        weight = MAX_XEN_WEIGHT;
+                else if (STARTS_WITH(CLASSNAME(ref), "KVM"))
+                        weight = MAX_KVM_WEIGHT;
                 id = "Maximum";
                 break;
         case SDC_RASD_INC:
                 num_procs = 1;
                 limit = 50;
-                weight = INC_XEN_WEIGHT;
+                if (STARTS_WITH(CLASSNAME(ref), "Xen"))
+                        weight = INC_XEN_WEIGHT;
+                else if (STARTS_WITH(CLASSNAME(ref), "KVM"))
+                        weight = INC_KVM_WEIGHT;
                 id = "Increment";
                 break;
         case SDC_RASD_DEF:
                 num_procs = 1;
                 limit = 0;
-                weight = DEFAULT_XEN_WEIGHT;
+                if (STARTS_WITH(CLASSNAME(ref), "Xen"))
+                        weight = DEFAULT_XEN_WEIGHT;
+                else if (STARTS_WITH(CLASSNAME(ref), "KVM"))
+                        weight = DEFAULT_KVM_WEIGHT;
                 id = "Default";
                 break;
         default:
@@ -455,6 +467,10 @@
                 CMSetProperty(inst, "Weight", 
                               (CMPIValue *)&weight, CMPI_uint32); 
         }
+        else if (STARTS_WITH(CLASSNAME(ref), "KVM")) {
+                CMSetProperty(inst, "Weight",
+                              (CMPIValue *)&weight, CMPI_uint32);
+        }
 
         inst_list_add(list, inst);
 
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.c
--- a/src/Virt_VirtualSystemManagementService.c	Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Virt_VirtualSystemManagementService.c	Mon Oct 03 02:51:26 2011 -0700
@@ -1012,6 +1012,8 @@
 
         if (STARTS_WITH(CLASSNAME(op), "Xen")) 
                 def_weight = DEFAULT_XEN_WEIGHT;
+        else if (STARTS_WITH(CLASSNAME(op), "QEMU"))
+                def_weight = DEFAULT_KVM_WEIGHT;
 
         rc = cu_get_u64_prop(inst, "Limit", &dev->dev.vcpu.limit);
         if (rc != CMPI_RC_OK)
diff -r fb09136deb49 -r 2c9a378e141c src/Virt_VirtualSystemManagementService.h
--- a/src/Virt_VirtualSystemManagementService.h	Tue Aug 30 08:48:36 2011 -0700
+++ b/src/Virt_VirtualSystemManagementService.h	Mon Oct 03 02:51:26 2011 -0700
@@ -24,6 +24,11 @@
 #define INC_XEN_WEIGHT MAX_XEN_WEIGHT / 2 
 #define DEFAULT_XEN_WEIGHT 1024
 
+#define MIN_KVM_WEIGHT 2
+#define MAX_KVM_WEIGHT 262144
+#define INC_KVM_WEIGHT 1
+#define DEFAULT_KVM_WEIGHT 1024
+
 CMPIStatus get_vsms(const CMPIObjectPath *reference,
                     CMPIInstance **_inst,
                     const CMPIBroker *broker,




More information about the Libvirt-cim mailing list