[libvirt] [PATCH] Add rlimits to lxc

Ryan Cleere rcleere at gmail.com
Sun Dec 7 03:17:18 UTC 2014


---
 src/conf/domain_conf.c   | 115 +++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |  12 +++++
 src/lxc/lxc_controller.c |  12 +++++
 src/util/virprocess.c    |   4 +-
 src/util/virprocess.h    |   3 ++
 5 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2d81c37..a673dc2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -26,6 +26,7 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <strings.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -1003,7 +1004,86 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,
     return -1;
 }
 
+static virDomainRLimitsPtr
+virDomainRLimitsNew(void)
+{
+    virDomainRLimitsPtr def = NULL;
+
+    if (VIR_ALLOC(def) < 0)
+        return NULL;
+
+    return def;
+}
+
+static virDomainRLimitsPtr
+virDomainRLimitParseXML(xmlNodePtr node)
+{
+    char *c = NULL;
+    long long val;
+    virDomainRLimitsPtr def;
 
+    if (!(def = virDomainRLimitsNew()))
+        return NULL;
+
+    if (node->type == XML_ELEMENT_NODE) {
+        c = (char *)xmlNodeGetContent(node);
+        if (virStrToLong_ll(c, NULL, 10, &val) < 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("could not parse rlimit value of %s"),
+                           c);
+            goto error;
+        }
+        VIR_FREE(c);
+
+        def->limit = val;
+        if (VIR_STRDUP(def->name, (char *)node->name) < 0)
+            goto error;
+
+        if (xmlStrEqual(node->name, BAD_CAST "as")) {
+            def->resource = RLIMIT_AS;
+        } else if (xmlStrEqual(node->name, BAD_CAST "core")) {
+            def->resource = RLIMIT_CORE;
+        } else if (xmlStrEqual(node->name, BAD_CAST "cpu")) {
+            def->resource = RLIMIT_CPU;
+        } else if (xmlStrEqual(node->name, BAD_CAST "data")) {
+            def->resource = RLIMIT_DATA;
+        } else if (xmlStrEqual(node->name, BAD_CAST "fsize")) {
+            def->resource = RLIMIT_FSIZE;
+        } else if (xmlStrEqual(node->name, BAD_CAST "locks")) {
+            def->resource = RLIMIT_LOCKS;
+        } else if (xmlStrEqual(node->name, BAD_CAST "memlock")) {
+            def->resource = RLIMIT_MEMLOCK;
+        } else if (xmlStrEqual(node->name, BAD_CAST "msgqueue")) {
+            def->resource = RLIMIT_MSGQUEUE;
+        } else if (xmlStrEqual(node->name, BAD_CAST "nice")) {
+            def->resource = RLIMIT_NICE;
+        } else if (xmlStrEqual(node->name, BAD_CAST "nofile")) {
+            def->resource = RLIMIT_NOFILE;
+        } else if (xmlStrEqual(node->name, BAD_CAST "nproc")) {
+            def->resource = RLIMIT_NPROC;
+        } else if (xmlStrEqual(node->name, BAD_CAST "rss")) {
+            def->resource = RLIMIT_RSS;
+        } else if (xmlStrEqual(node->name, BAD_CAST "rtprio")) {
+            def->resource = RLIMIT_RTPRIO;
+        } else if (xmlStrEqual(node->name, BAD_CAST "sigpending")) {
+            def->resource = RLIMIT_SIGPENDING;
+        } else if (xmlStrEqual(node->name, BAD_CAST "stack")) {
+            def->resource = RLIMIT_STACK;
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("could not determine resource type of '%s'"),
+                           node->name);
+            goto error;
+        }
+    }
+
+    return def;
+
+ error:
+    VIR_FREE(c);
+    VIR_FREE(def);
+    return NULL;
+}
 
 static void
 virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
@@ -14180,6 +14260,28 @@ virDomainDefParseXML(xmlDocPtr xml,
 
     virHashFree(bootHash);
 
+    if ((node = virXPathNode("./rlimits[1]", ctxt)) != NULL && (n = virXMLChildElementCount(node)) > 0) {
+        xmlNodePtr cur = node->children;
+        if (n && VIR_ALLOC_N(def->rlimits, n) < 0)
+            goto error;
+
+        for (i = 0; i < n; i++) {
+            if (!(def->rlimits[i] = virDomainRLimitParseXML(cur)))
+                goto error;
+            def->nrlimits++;
+            for (j = 0; j < i; j++) {
+                if (def->rlimits[j]->resource == def->rlimits[i]->resource) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("duplicate rlimit resources '%s'"),
+                                   def->rlimits[j]->name);
+                    goto error;
+                }
+            }
+            cur = cur->next;
+        }
+    }
+    VIR_FREE(node);
+
     return def;
 
  error:
@@ -19759,6 +19861,19 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             goto error;
     }
 
+    if (def->nrlimits > 0) {
+        virBufferAddLit(buf, "<rlimits>\n");
+        virBufferAdjustIndent(buf, 2);
+        for (n = 0; n < def->nrlimits; n++) {
+            virBufferAsprintf(buf, "<%s>%lld</%s>\n",
+                              def->rlimits[n]->name,
+                              def->rlimits[n]->limit,
+                              def->rlimits[n]->name);
+        }
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "</rlimits>\n");
+    }
+
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</domain>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 439f3c0..abad30e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2021,6 +2021,15 @@ struct _virDomainPowerManagement {
     int s4;
 };
 
+typedef struct _virDomainRLimits virDomainRLimits;
+typedef virDomainRLimits *virDomainRLimitsPtr;
+
+struct _virDomainRLimits {
+    char *name;
+    int resource;
+    long long limit;
+};
+
 /*
  * Guest VM main configuration
  *
@@ -2138,6 +2147,9 @@ struct _virDomainDef {
     size_t nshmems;
     virDomainShmemDefPtr *shmems;
 
+    size_t nrlimits;
+    virDomainRLimitsPtr *rlimits;
+
     /* Only 1 */
     virDomainWatchdogDefPtr watchdog;
     virDomainMemballoonDefPtr memballoon;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 53a2c8d..ef5551e 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -2490,6 +2490,18 @@ int main(int argc, char *argv[])
         }
     }
 
+    VIR_INFO("nrlimits = %d", (int)ctrl->def->nrlimits);
+    if (ctrl->def->nrlimits > 0) {
+        struct rlimit rlim;
+        int n;
+        for (i = 0; i < ctrl->def->nrlimits; i++) {
+            rlim.rlim_max = rlim.rlim_cur = ctrl->def->rlimits[i]->limit;
+            n = virProcessPrLimit(0, ctrl->def->rlimits[i]->resource, &rlim);
+            if (n < 0)
+                goto cleanup;
+        }
+    }
+
     rc = virLXCControllerRun(ctrl);
 
  cleanup:
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 0c8a32f..9bb5370 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -675,13 +675,13 @@ int virProcessSetNamespaces(size_t nfdlist,
 }
 
 #if HAVE_PRLIMIT
-static int
+int
 virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim)
 {
     return prlimit(pid, resource, rlim, NULL);
 }
 #elif HAVE_SETRLIMIT
-static int
+int
 virProcessPrLimit(pid_t pid ATTRIBUTE_UNUSED,
                   int resource ATTRIBUTE_UNUSED,
                   struct rlimit *rlim ATTRIBUTE_UNUSED)
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index bcaede5..045f8d4 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -22,6 +22,7 @@
 #ifndef __VIR_PROCESS_H__
 # define __VIR_PROCESS_H__
 
+# include <sys/resource.h>
 # include <sys/types.h>
 
 # include "internal.h"
@@ -73,4 +74,6 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque);
 int virProcessRunInMountNamespace(pid_t pid,
                                   virProcessNamespaceCallback cb,
                                   void *opaque);
+
+int virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim);
 #endif /* __VIR_PROCESS_H__ */
-- 
1.9.3 (Apple Git-50)




More information about the libvir-list mailing list