---
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