<div dir="ltr">---<div><div> docs/<a href="http://formatdomain.html.in">formatdomain.html.in</a>     | 49 +++++++++++++++++++++++</div><div> docs/schemas/domaincommon.rng | 89 +++++++++++++++++++++++++++++++++++++++++</div><div> src/conf/domain_conf.c        | 92 +++++++++++++++++++++++++++++++++++++++++++</div><div> src/conf/domain_conf.h        | 33 ++++++++++++++++</div><div> src/libvirt_private.syms      |  1 +</div><div> src/lxc/lxc_controller.c      | 32 +++++++++++++++</div><div> src/util/virprocess.c         |  4 +-</div><div> src/util/virprocess.h         |  2 +</div><div> 8 files changed, 300 insertions(+), 2 deletions(-)</div><div><br></div><div>diff --git a/docs/<a href="http://formatdomain.html.in">formatdomain.html.in</a> b/docs/<a href="http://formatdomain.html.in">formatdomain.html.in</a></div><div>index f8d5f89..5aec51c 100644</div><div>--- a/docs/<a href="http://formatdomain.html.in">formatdomain.html.in</a></div><div>+++ b/docs/<a href="http://formatdomain.html.in">formatdomain.html.in</a></div><div>@@ -348,6 +348,55 @@</div><div>     </pre></div><div><br></div><div><br></div><div>+    <p></div><div>+      If you want to set an rlimit of the containter init process instead of</div><div>+      inheriting from the host init, set the <code>rlimits</code> element. You</div><div>+      are able to set any of the rlimits that setrlimits is able to set using</div><div>+      any of the following sub-elements:</div><div>+    </p></div><div>+</div><div>+    <dl></div><div>+      <dt><code>as</code></dt></div><div>+      <dd>Used to set RLIMIT_AS.</dd></div><div>+      <dt><code>core</code></dt></div><div>+      <dd>Used to set RLIMIT_CORE.</dd></div><div>+      <dt><code>cpu</code></dt></div><div>+      <dd>Used to set RLIMIT_CPU.</dd></div><div>+      <dt><code>data</code></dt></div><div>+      <dd>Used to set RLIMIT_DATA.</dd></div><div>+      <dt><code>fsize</code></dt></div><div>+      <dd>Used to set RLIMIT_FSIZE.</dd></div><div>+      <dt><code>locks</code></dt></div><div>+      <dd>Used to set RLIMIT_LOCKS.</dd></div><div>+      <dt><code>memlock</code></dt></div><div>+      <dd>Used to set RLIMIT_MEMLOCK.</dd></div><div>+      <dt><code>msgqueue</code></dt></div><div>+      <dd>Used to set RLIMIT_MSGQUEUE.</dd></div><div>+      <dt><code>nice</code></dt></div><div>+      <dd>Used to set RLIMIT_NICE.</dd></div><div>+      <dt><code>nofile</code></dt></div><div>+      <dd>Used to set RLIMIT_NOFILE.</dd></div><div>+      <dt><code>nproc</code></dt></div><div>+      <dd>Used to set RLIMIT_NPROC.</dd></div><div>+      <dt><code>rss</code></dt></div><div>+      <dd>Used to set RLIMIT_RSS.</dd></div><div>+      <dt><code>rtprio</code></dt></div><div>+      <dd>Used to set RLIMIT_RTPRIO.</dd></div><div>+      <dt><code>rttime</code></dt></div><div>+      <dd>Used to set RLIMIT_RTTIME.</dd></div><div>+      <dt><code>sigpending</code></dt></div><div>+      <dd>Used to set RLIMIT_SIGPENDING.</dd></div><div>+      <dt><code>stack</code></dt></div><div>+      <dd>Used to set RLIMIT_STACK.</dd></div><div>+    </dl></div><div>+</div><div>+    <pre></div><div>+  &lt;rlimits&gt;</div><div>+    &lt;nofile&gt;10240&lt;/nofile&gt;</div><div>+  &lt;/rlimits&gt;</div><div>+    </pre></div><div>+</div><div>+</div><div>     <h3><a name="elementsSysinfo">SMBIOS System Information</a></h3></div><div><br></div><div>     <p></div><div>diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng</div><div>index d467dce..b98f8d5 100644</div><div>--- a/docs/schemas/domaincommon.rng</div><div>+++ b/docs/schemas/domaincommon.rng</div><div>@@ -59,6 +59,9 @@</div><div>           <ref name="idmap"/></div><div>         </optional></div><div>         <optional></div><div>+          <ref name="rlimits"/></div><div>+        </optional></div><div>+        <optional></div><div>           <ref name="devices"/></div><div>         </optional></div><div>         <zeroOrMore></div><div>@@ -570,6 +573,92 @@</div><div>       </interleave></div><div>     </element></div><div>   </define></div><div>+  <define name="rlimits"></div><div>+    <element name="rlimits"></div><div>+      <interleave></div><div>+        <optional></div><div>+          <element name="cpu"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="fsize"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="data"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="stack"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="core"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="rss"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="nproc"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="nofile"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="memlock"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="as"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="locks"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="sigpending"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="msgqueue"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="nice"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="rtprio"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+        <optional></div><div>+          <element name="rttime"></div><div>+            <ref name='scaledInteger'/></div><div>+          </element></div><div>+        </optional></div><div>+      </interleave></div><div>+    </element></div><div>+  </define></div><div>   <!--</div><div>       Resources usage defines the amount of memory (maximum and possibly</div><div>       current usage) and number of virtual CPUs used by that domain.</div><div>diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c</div><div>index d562e1a..399976e 100644</div><div>--- a/src/conf/domain_conf.c</div><div>+++ b/src/conf/domain_conf.c</div><div>@@ -772,6 +772,24 @@ VIR_ENUM_IMPL(virDomainLoader,</div><div>               "rom",</div><div>               "pflash")</div><div><br></div><div>+VIR_ENUM_IMPL(virDomainRLimit, VIR_DOMAIN_RLIMIT_LAST,</div><div>+              "cpu",</div><div>+              "fsize",</div><div>+              "data",</div><div>+              "stack",</div><div>+              "core",</div><div>+              "rss",</div><div>+              "nproc",</div><div>+              "nofile",</div><div>+              "memlock",</div><div>+              "as",</div><div>+              "locks",</div><div>+              "sigpending",</div><div>+              "msgqueue",</div><div>+              "nice",</div><div>+              "rtprio",</div><div>+              "rttime")</div><div>+</div><div> /* Internal mapping: subset of block job types that can be present in</div><div>  * <mirror> XML (remaining types are not two-phase). */</div><div> VIR_ENUM_DECL(virDomainBlockJob)</div><div>@@ -979,7 +997,40 @@ virDomainBlkioDeviceParseXML(xmlNodePtr root,</div><div>     return -1;</div><div> }</div><div><br></div><div>+static virDomainRLimitsPtr</div><div>+virDomainRLimitParseXML(xmlNodePtr node)</div><div>+{</div><div>+    char *c = NULL;</div><div>+    long long val;</div><div>+    virDomainRLimitsPtr def;</div><div>+</div><div>+    if (VIR_ALLOC(def) < 0)</div><div>+        return NULL;</div><div>+    if (node->type == XML_ELEMENT_NODE) {</div><div>+        c = (char *)xmlNodeGetContent(node);</div><div>+        if (virStrToLong_ll(c, NULL, 10, &val) < 0) {</div><div>+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,</div><div>+                           _("could not parse rlimit value of %s"),</div><div>+                           c);</div><div>+            goto error;</div><div>+        }</div><div>+        VIR_FREE(c);</div><div>+</div><div>+        def->limit = val;</div><div>+        if ((def->resource = virDomainRLimitTypeFromString((const char *)node->name)) < 0) {</div><div>+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,</div><div>+                           _("could not determine resource type of '%s'"),</div><div>+                           node->name);</div><div>+            goto error;</div><div>+        }</div><div>+    }</div><div>+    return def;</div><div><br></div><div>+  error:</div><div>+    VIR_FREE(c);</div><div>+    VIR_FREE(def);</div><div>+    return NULL;</div><div>+}</div><div><br></div><div> static void</div><div> virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)</div><div>@@ -14423,6 +14474,34 @@ virDomainDefParseXML(xmlDocPtr xml,</div><div><br></div><div>     virHashFree(bootHash);</div><div><br></div><div>+    if ((node = virXPathNode("./rlimits[1]", ctxt)) != NULL && (n = virXMLChildElementCount(node)) > 0) {</div><div>+        xmlNodePtr cur = node->children;</div><div>+        if (n && VIR_ALLOC_N(def->rlimits, n) < 0)</div><div>+            goto error;</div><div>+</div><div>+        for (i = 0; i < n; i++) {</div><div>+            if (!(def->rlimits[i] = virDomainRLimitParseXML(cur))) {</div><div>+                for (j = 0; j < i; j++)</div><div>+                    VIR_FREE(def->rlimits[j]);</div><div>+                VIR_FREE(def->rlimits);</div><div>+                goto error;</div><div>+            }</div><div>+            def->nrlimits++;</div><div>+            for (j = 0; j < i; j++) {</div><div>+                if (def->rlimits[j]->resource == def->rlimits[i]->resource) {</div><div>+                    virReportError(VIR_ERR_XML_ERROR,</div><div>+                                   _("duplicate rlimit resources '%s'"),</div><div>+<span class="" style="white-space:pre">                               </span>   virDomainRLimitTypeToString(def->rlimits[j]->resource));</div><div>+                    for (int k = 0; k < i; k++)</div><div>+                        VIR_FREE(def->rlimits[k]);</div><div>+                    VIR_FREE(def->rlimits);</div><div>+                    goto error;</div><div>+                }</div><div>+            }</div><div>+            cur = cur->next;</div><div>+        }</div><div>+    }</div><div>+</div><div>     return def;</div><div><br></div><div>  error:</div><div>@@ -20048,6 +20127,19 @@ virDomainDefFormatInternal(virDomainDefPtr def,</div><div>             goto error;</div><div>     }</div><div><br></div><div>+    if (def->nrlimits > 0) {</div><div>+        virBufferAddLit(buf, "<rlimits>\n");</div><div>+        virBufferAdjustIndent(buf, 2);</div><div>+        for (n = 0; n < def->nrlimits; n++) {</div><div>+            virBufferAsprintf(buf, "<%s>%lld</%s>\n",</div><div>+                  virDomainRLimitTypeToString(def->rlimits[n]->resource),</div><div>+                  def->rlimits[n]->limit,</div><div>+                  virDomainRLimitTypeToString(def->rlimits[n]->resource));</div><div>+        }</div><div>+       virBufferAdjustIndent(buf, -2);</div><div>+       virBufferAddLit(buf, "</rlimits>\n");</div><div>+    }</div><div>+</div><div>     virBufferAdjustIndent(buf, -2);</div><div>     virBufferAddLit(buf, "</domain>\n");</div><div><br></div><div>diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h</div><div>index 93f2314..b032202 100644</div><div>--- a/src/conf/domain_conf.h</div><div>+++ b/src/conf/domain_conf.h</div><div>@@ -1851,6 +1851,27 @@ typedef enum {</div><div>     VIR_DOMAIN_CLOCK_BASIS_LAST</div><div> } virDomainClockBasis;</div><div><br></div><div>+typedef enum {</div><div>+    VIR_DOMAIN_RLIMIT_CPU,</div><div>+    VIR_DOMAIN_RLIMIT_FSIZE,</div><div>+    VIR_DOMAIN_RLIMIT_DATA,</div><div>+    VIR_DOMAIN_RLIMIT_STACK,</div><div>+    VIR_DOMAIN_RLIMIT_CORE,</div><div>+    VIR_DOMAIN_RLIMIT_RSS,</div><div>+    VIR_DOMAIN_RLIMIT_NPROC,</div><div>+    VIR_DOMAIN_RLIMIT_NOFILE,</div><div>+    VIR_DOMAIN_RLIMIT_MEMLOCK,</div><div>+    VIR_DOMAIN_RLIMIT_AS,</div><div>+    VIR_DOMAIN_RLIMIT_LOCKS,</div><div>+    VIR_DOMAIN_RLIMIT_SIGPENDING,</div><div>+    VIR_DOMAIN_RLIMIT_MSGQUEUE,</div><div>+    VIR_DOMAIN_RLIMIT_NICE,</div><div>+    VIR_DOMAIN_RLIMIT_RTPRIO,</div><div>+    VIR_DOMAIN_RLIMIT_RTTIME,</div><div>+</div><div>+    VIR_DOMAIN_RLIMIT_LAST</div><div>+} virDomainRLimit;</div><div>+</div><div> typedef struct _virDomainClockDef virDomainClockDef;</div><div> typedef virDomainClockDef *virDomainClockDefPtr;</div><div> struct _virDomainClockDef {</div><div>@@ -2039,6 +2060,14 @@ struct _virDomainPowerManagement {</div><div>     int s4;</div><div> };</div><div><br></div><div>+typedef struct _virDomainRLimits virDomainRLimits;</div><div>+typedef virDomainRLimits *virDomainRLimitsPtr;</div><div>+</div><div>+struct _virDomainRLimits {</div><div>+    int resource;</div><div>+    long long limit;</div><div>+};</div><div>+</div><div> /*</div><div>  * Guest VM main configuration</div><div>  *</div><div>@@ -2156,6 +2185,9 @@ struct _virDomainDef {</div><div>     size_t nshmems;</div><div>     virDomainShmemDefPtr *shmems;</div><div><br></div><div>+    size_t nrlimits;</div><div>+    virDomainRLimitsPtr *rlimits;</div><div>+</div><div>     /* Only 1 */</div><div>     virDomainWatchdogDefPtr watchdog;</div><div>     virDomainMemballoonDefPtr memballoon;</div><div>@@ -2844,6 +2876,7 @@ VIR_ENUM_DECL(virDomainRNGModel)</div><div> VIR_ENUM_DECL(virDomainRNGBackend)</div><div> VIR_ENUM_DECL(virDomainTPMModel)</div><div> VIR_ENUM_DECL(virDomainTPMBackend)</div><div>+VIR_ENUM_DECL(virDomainRLimit)</div><div> /* from libvirt.h */</div><div> VIR_ENUM_DECL(virDomainState)</div><div> VIR_ENUM_DECL(virDomainNostateReason)</div><div>diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms</div><div>index bd7870f..7b71ff1 100644</div><div>--- a/src/libvirt_private.syms</div><div>+++ b/src/libvirt_private.syms</div><div>@@ -1896,6 +1896,7 @@ virProcessGetNamespaces;</div><div> virProcessGetStartTime;</div><div> virProcessKill;</div><div> virProcessKillPainfully;</div><div>+virProcessPrLimit;</div><div> virProcessRunInMountNamespace;</div><div> virProcessSetAffinity;</div><div> virProcessSetMaxFiles;</div><div>diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c</div><div>index 8a7c7e8..5c63a1b 100644</div><div>--- a/src/lxc/lxc_controller.c</div><div>+++ b/src/lxc/lxc_controller.c</div><div>@@ -798,6 +798,35 @@ static int virLXCControllerSetupCgroupLimits(virLXCControllerPtr ctrl)</div><div>     return ret;</div><div> }</div><div><br></div><div>+static int virLXCControllerSetupRLimits(virLXCControllerPtr ctrl)</div><div>+{</div><div>+    int i, ret = -1;</div><div>+    struct rlimit rlim;</div><div>+</div><div>+    VIR_DEBUG("Setting up rlimits");</div><div>+</div><div>+    VIR_DEBUG("nrlimits = %d", (int)ctrl->def->nrlimits);</div><div>+    VIR_DEBUG("setting limits on process %d", ctrl->initpid);</div><div>+    if (ctrl->def->nrlimits > 0) {</div><div>+        for (i = 0; i < ctrl->def->nrlimits; i++) {</div><div>+            rlim.rlim_max = rlim.rlim_cur = ctrl->def->rlimits[i]->limit;</div><div>+            VIR_DEBUG("Setting rlimit %s(%d) on pid %d to %lld",</div><div>+                     virDomainRLimitTypeToString(ctrl->def->rlimits[i]->resource),</div><div>+                     ctrl->def->rlimits[i]->resource,</div><div>+                     ctrl->initpid,</div><div>+                     ctrl->def->rlimits[i]->limit);</div><div>+            if (virProcessPrLimit(ctrl->initpid, ctrl->def->rlimits[i]->resource, &rlim) < 0) {</div><div>+                virReportSystemError(errno, "%s",</div><div>+                                     _("Unable to set rlimit"));</div><div>+                goto cleanup;</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+    ret = 0;</div><div>+  cleanup:</div><div>+    return ret;</div><div>+}</div><div>+</div><div><br></div><div> static void virLXCControllerClientCloseHook(virNetServerClientPtr client)</div><div> {</div><div>@@ -2318,6 +2347,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)</div><div>     if (virLXCControllerSetupCgroupLimits(ctrl) < 0)</div><div>         goto cleanup;</div><div><br></div><div>+    if (virLXCControllerSetupRLimits(ctrl) < 0)</div><div>+        goto cleanup;</div><div>+</div><div>     if (virLXCControllerSetupUserns(ctrl) < 0)</div><div>         goto cleanup;</div><div><br></div><div>diff --git a/src/util/virprocess.c b/src/util/virprocess.c</div><div>index d0a1500..d83ae28 100644</div><div>--- a/src/util/virprocess.c</div><div>+++ b/src/util/virprocess.c</div><div>@@ -676,13 +676,13 @@ int virProcessSetNamespaces(size_t nfdlist,</div><div> }</div><div><br></div><div> #if HAVE_PRLIMIT</div><div>-static int</div><div>+int</div><div> virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim)</div><div> {</div><div>     return prlimit(pid, resource, rlim, NULL);</div><div> }</div><div> #elif HAVE_SETRLIMIT</div><div>-static int</div><div>+int</div><div> virProcessPrLimit(pid_t pid ATTRIBUTE_UNUSED,</div><div>                   int resource ATTRIBUTE_UNUSED,</div><div>                   struct rlimit *rlim ATTRIBUTE_UNUSED)</div><div>diff --git a/src/util/virprocess.h b/src/util/virprocess.h</div><div>index bcaede5..c40b41a 100644</div><div>--- a/src/util/virprocess.h</div><div>+++ b/src/util/virprocess.h</div><div>@@ -22,6 +22,7 @@</div><div> #ifndef __VIR_PROCESS_H__</div><div> # define __VIR_PROCESS_H__</div><div><br></div><div>+# include <sys/resource.h></div><div> # include <sys/types.h></div><div><br></div><div> # include "internal.h"</div><div>@@ -73,4 +74,5 @@ typedef int (*virProcessNamespaceCallback)(pid_t pid, void *opaque);</div><div> int virProcessRunInMountNamespace(pid_t pid,</div><div>                                   virProcessNamespaceCallback cb,</div><div>                                   void *opaque);</div><div>+int virProcessPrLimit(pid_t pid, int resource, struct rlimit *rlim);</div><div> #endif /* __VIR_PROCESS_H__ */</div></div></div>