]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
LXC implement memory control APIs
authorRyota Ozaki <ozaki.ryota@gmail.com>
Wed, 7 Oct 2009 13:26:23 +0000 (15:26 +0200)
committerDaniel Veillard <veillard@redhat.com>
Wed, 7 Oct 2009 13:26:23 +0000 (15:26 +0200)
The patch implements the missing memory control APIs for lxc, i.e.,
domainGetMaxMemory, domainSetMaxMemory, domainSetMemory, and improves
domainGetInfo to return proper amount of used memory via cgroup.

* src/libvirt_private.syms: Export virCgroupGetMemoryUsage
  and add missing virCgroupSetMemory
* src/lxc/lxc_driver.c: Implement missing memory functions
* src/util/cgroup.c, src/util/cgroup.h: Add the function
  to get used memory

src/libvirt_private.syms
src/lxc/lxc_driver.c
src/util/cgroup.c
src/util/cgroup.h

index 952ed2968c5fea72357aa3b64513e3956fdfb3cb..37c729c72508f66d58cd59aa4c562dbd717c8a78 100644 (file)
@@ -53,6 +53,8 @@ virCgroupForDriver;
 virCgroupRemove;
 virCgroupFree;
 virCgroupAddTask;
+virCgroupSetMemory;
+virCgroupGetMemoryUsage;
 virCgroupSetCpuShares;
 virCgroupGetCpuShares;
 virCgroupDenyDevicePath;
index 5fb4105a0bd24b3ec7c60da4c91bca6e426488cf..8ec4ae4964cc64ca10325724f708e5e69bedc44b 100644 (file)
@@ -450,6 +450,7 @@ static int lxcDomainGetInfo(virDomainPtr dom,
 
     if (!virDomainIsActive(vm) || driver->cgroup == NULL) {
         info->cpuTime = 0;
+        info->memory = vm->def->memory;
     } else {
         if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
             lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
@@ -458,13 +459,18 @@ static int lxcDomainGetInfo(virDomainPtr dom,
         }
 
         if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) {
-            lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
+            lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
+                     "%s", _("cannot read cputime for domain"));
+            goto cleanup;
+        }
+        if (virCgroupGetMemoryUsage(cgroup, &(info->memory)) < 0) {
+            lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
+                     "%s", _("cannot read memory usage for domain"));
             goto cleanup;
         }
     }
 
     info->maxMem = vm->def->maxmem;
-    info->memory = vm->def->memory;
     info->nrVirtCpu = 1;
     ret = 0;
 
@@ -501,6 +507,112 @@ cleanup:
     return ret;
 }
 
+/* Returns max memory in kb, 0 if error */
+static unsigned long lxcDomainGetMaxMemory(virDomainPtr dom) {
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    unsigned long ret = 0;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    lxcDriverUnlock(driver);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
+                         _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    ret = vm->def->maxmem;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    lxcDriverUnlock(driver);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
+                         _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (newmax < vm->def->memory) {
+        lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG,
+                         "%s", _("cannot set max memory lower than current memory"));
+        goto cleanup;
+    }
+
+    vm->def->maxmem = newmax;
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
+    lxc_driver_t *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    virCgroupPtr cgroup = NULL;
+    int ret = -1;
+
+    lxcDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    lxcDriverUnlock(driver);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN,
+                 _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (newmem > vm->def->maxmem) {
+        lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG,
+                 "%s", _("cannot set memory higher than max memory"));
+        goto cleanup;
+    }
+
+    if (virDomainIsActive(vm)) {
+        if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
+            lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR,
+                     _("Unable to get cgroup for %s\n"), vm->def->name);
+            goto cleanup;
+        }
+
+        if (virCgroupSetMemory(cgroup, newmem) < 0) {
+            lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED,
+                     "%s", _("cannot set memory for domain"));
+            goto cleanup;
+        }
+    } else {
+        vm->def->memory = newmem;
+    }
+    ret = 0;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    if (cgroup)
+        virCgroupFree(&cgroup);
+    return ret;
+}
+
 static char *lxcDomainDumpXML(virDomainPtr dom,
                               int flags)
 {
@@ -2103,9 +2215,9 @@ static virDriver lxcDriver = {
     NULL, /* domainReboot */
     lxcDomainDestroy, /* domainDestroy */
     lxcGetOSType, /* domainGetOSType */
-    NULL, /* domainGetMaxMemory */
-    NULL, /* domainSetMaxMemory */
-    NULL, /* domainSetMemory */
+    lxcDomainGetMaxMemory, /* domainGetMaxMemory */
+    lxcDomainSetMaxMemory, /* domainSetMaxMemory */
+    lxcDomainSetMemory, /* domainSetMemory */
     lxcDomainGetInfo, /* domainGetInfo */
     NULL, /* domainSave */
     NULL, /* domainRestore */
index 2e646fdf615967ceaffa3f1169719c14feab1daa..e56d293188ba423d41d0b4519eb4285d53d8ebfc 100644 (file)
@@ -701,6 +701,26 @@ int virCgroupSetMemory(virCgroupPtr group, unsigned long kb)
                                 kb << 10);
 }
 
+/**
+ * virCgroupGetMemoryUsage:
+ *
+ * @group: The cgroup to change memory for
+ * @kb: Pointer to returned used memory in kilobytes
+ *
+ * Returns: 0 on success
+ */
+int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+{
+    uint64_t usage_in_bytes;
+    int ret;
+    ret = virCgroupGetValueU64(group,
+                               VIR_CGROUP_CONTROLLER_MEMORY,
+                               "memory.usage_in_bytes", &usage_in_bytes);
+    if (ret == 0)
+        *kb = (unsigned long) usage_in_bytes >> 10;
+    return ret;
+}
+
 /**
  * virCgroupDenyAllDevices:
  *
index aba56c69cd0ae4b0de803df032268c49c90fa0cf..aa36632c166ba8e48d42b902baa8bdd12b83a8d5 100644 (file)
@@ -41,6 +41,7 @@ int virCgroupForDomain(virCgroupPtr driver,
 int virCgroupAddTask(virCgroupPtr group, pid_t pid);
 
 int virCgroupSetMemory(virCgroupPtr group, unsigned long kb);
+int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb);
 
 int virCgroupDenyAllDevices(virCgroupPtr group);