--- docs/formatdomain.html.in | 12 ++++++ docs/schemas/domaincommon.rng | 12 ++++++ src/conf/domain_conf.c | 88 +++++++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 2 + 4 files changed, 111 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index e1fe0c4..8ef20c0 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1673,6 +1673,18 @@ default read-write access is given (currently only works for QEMU/KVM driver). </dd> + + <dt><code>space_hard_limit</code></dt> + <dd> + Maximum space available to this guests's filesystem. + </dd> + + <dt><code>space_soft_limit</code></dt> + <dd> + Maximum space available to this guest's filesystem. The container is + is permitted to exceed its soft limits for a grace period of time. Afterwards + the hard limit is enforced. + </dd> </dl> <h4><a name="elementsAddress">Device Addresses</a></h4> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8419ccc..f068ff7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1300,6 +1300,18 @@ <ref name="address"/> </optional> </interleave> + <interleave> + <optional> + <element name="space_hard_limit"> + <ref name='scaledInteger'/> + </element> + </optional> + <optional> + <element name="space_soft_limit"> + <ref name='scaledInteger'/> + </element> + </optional> + </interleave> </element> </define> <!-- diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3fce7e5..d5e01a8 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4086,14 +4086,72 @@ cleanup: goto cleanup; } + +/* Parse a value located at XPATH within CTXT, and store the + * result into val. If REQUIRED, then the value must exist; + * otherwise, the value is optional. The value is in bytes. + * Return 0 on success, -1 on failure after issuing error. */ +static int +virDomainParseScaledValue(const char *xpath, + xmlXPathContextPtr ctxt, + unsigned long long *val, + unsigned long long scale, + unsigned long long max, + bool required) +{ + char *xpath_full = NULL; + char *unit = NULL; + int ret = -1; + unsigned long long bytes; + + *val = 0; + if (virAsprintf(&xpath_full, "string(%s)", xpath) < 0) { + virReportOOMError(); + goto cleanup; + } + ret = virXPathULongLong(xpath_full, ctxt, &bytes); + if (ret < 0) { + if (ret == -2) + virDomainReportError(VIR_ERR_XML_ERROR, + _("could not parse memory element %s"), + xpath); + else if (required) + virDomainReportError(VIR_ERR_XML_ERROR, + _("missing element %s"), + xpath); + else + ret = 0; + goto cleanup; + } + VIR_FREE(xpath_full); + + if (virAsprintf(&xpath_full, "string(%s/@unit)", xpath) < 0) { + virReportOOMError(); + goto cleanup; + } + unit = virXPathString(xpath_full, ctxt); + + if (virScaleInteger(&bytes, unit, scale, max) < 0) + goto cleanup; + + *val = bytes; + ret = 0; +cleanup: + VIR_FREE(xpath_full); + VIR_FREE(unit); + return ret; +} + + /* Parse the XML definition for a disk * @param node XML nodeset to parse for disk definition */ static virDomainFSDefPtr virDomainFSDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, unsigned int flags) { virDomainFSDefPtr def; - xmlNodePtr cur; + xmlNodePtr cur, safe_node = ctxt->node; char *type = NULL; char *fsdriver = NULL; char *source = NULL; @@ -4101,6 +4159,8 @@ virDomainFSDefParseXML(xmlNodePtr node, char *accessmode = NULL; char *wrpolicy = NULL; + ctxt->node = node; + if (VIR_ALLOC(def) < 0) { virReportOOMError(); return NULL; @@ -4128,6 +4188,18 @@ virDomainFSDefParseXML(xmlNodePtr node, def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; } + if (virDomainParseScaledValue("./space_hard_limit[1]", ctxt, + &def->space_hard_limit, 1, + ULONG_LONG_MAX, + false) < 0) + goto error; + + if (virDomainParseScaledValue("./space_soft_limit[1]", ctxt, + &def->space_soft_limit, 1, + ULONG_LONG_MAX, + false) < 0) + goto error; + cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { @@ -4194,6 +4266,7 @@ virDomainFSDefParseXML(xmlNodePtr node, goto error; cleanup: + ctxt->node = safe_node; VIR_FREE(type); VIR_FREE(fsdriver); VIR_FREE(target); @@ -6883,7 +6956,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, goto error; } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) { dev->type = VIR_DOMAIN_DEVICE_FS; - if (!(dev->data.fs = virDomainFSDefParseXML(node, flags))) + if (!(dev->data.fs = virDomainFSDefParseXML(node, ctxt, flags))) goto error; } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { dev->type = VIR_DOMAIN_DEVICE_NET; @@ -8404,7 +8478,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, if (n && VIR_ALLOC_N(def->fss, n) < 0) goto no_memory; for (i = 0 ; i < n ; i++) { - virDomainFSDefPtr fs = virDomainFSDefParseXML(nodes[i], + virDomainFSDefPtr fs = virDomainFSDefParseXML(nodes[i], ctxt, flags); if (!fs) goto error; @@ -11101,6 +11175,14 @@ virDomainFSDefFormat(virBufferPtr buf, if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; + + if (def->space_hard_limit) + virBufferAsprintf(buf, " <space_hard_limit unit='B'>" + "%llu</space_hard_limit>\n", def->space_hard_limit); + if (def->space_soft_limit) { + virBufferAsprintf(buf, " <space_soft_limit unit='B'>" + "%llu</space_soft_limit>\n", def->space_soft_limit); + } virBufferAddLit(buf, " </filesystem>\n"); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5aa8fc1..7331ef5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -692,6 +692,8 @@ struct _virDomainFSDef { char *dst; unsigned int readonly : 1; virDomainDeviceInfo info; + unsigned long long space_hard_limit; /* in bytes */ + unsigned long long space_soft_limit; /* in bytes */ }; -- 1.7.10 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list