From: "Daniel P. Berrange" <berrange(a)redhat.com>
Introduce a new syntax for filesystems to allow use of a RAM
filesystem
<filesystem type='ram'>
<source usage='10' units='MiB'/>
<target dir='/mnt'/>
</filesystem>
The usage units default to KiB to limit consumption of host memory.
* docs/formatdomain.html.in: Document new syntax
* docs/schemas/domaincommon.rng: Add new attributes
* src/conf/domain_conf.c: Parsing/formatting of RAM filesystems
* src/lxc/lxc_container.c: Mounting of RAM filesystems
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
docs/formatdomain.html.in | 9 ++++++-
docs/schemas/domaincommon.rng | 18 +++++++++++++
src/conf/domain_conf.c | 58 +++++++++++++++++++++++++++--------------
src/conf/domain_conf.h | 5 ++++
src/lxc/lxc_container.c | 49 ++++++++++++++++++++++++++++++++++
5 files changed, 118 insertions(+), 21 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 1f30772..99ca26e 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1630,6 +1630,12 @@
format will be autodetected. Only used by LXC driver
<span class="since">(since 0.9.5)</span>.
</dd>
+ <dt><code>type='ram'</code></dt>
+ <dd>
+ An in-memory filesystem, using memory from the host OS.
+ The source element has a single attribute <code>usage</code>
+ which gives the memory usage limit in kibibytes.
+ <span class="since"> (since 0.9.13)</span></dd>
</dl>
The filesystem block has an optional attribute <code>accessmode</code>
@@ -1669,7 +1675,8 @@
The resource on the host that is being accessed in the guest. The
<code>name</code> attribute must be used with
<code>type='template'</code>, and the
<code>dir</code> attribute must
- be used with <code>type='mount'</code>
+ be used with <code>type='mount'</code>. The
<code>usage</code> attribute
+ is used with <code>type='ram'</code> to set the memory limit
in KB.
</dd>
<dt><code>target</code></dt>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 46e539d..4a04a65 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1289,6 +1289,24 @@
</element>
</interleave>
</group>
+ <group>
+ <attribute name="type">
+ <value>ram</value>
+ </attribute>
+ <interleave>
+ <element name="source">
+ <attribute name="usage">
+ <ref name="unsignedLong"/>
+ </attribute>
+ <optional>
+ <attribute name='unit'>
+ <ref name='unit'/>
+ </attribute>
+ </optional>
+ <empty/>
+ </element>
+ </interleave>
+ </group>
</choice>
<interleave>
<element name="target">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5ea264f..a653fe6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -262,7 +262,8 @@ VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
"mount",
"block",
"file",
- "template")
+ "template",
+ "ram")
VIR_ENUM_IMPL(virDomainFSDriverType, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
"default",
@@ -4210,6 +4211,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
char *target = NULL;
char *accessmode = NULL;
char *wrpolicy = NULL;
+ char *usage = NULL;
ctxt->node = node;
@@ -4297,7 +4299,8 @@ virDomainFSDefParseXML(xmlNodePtr node,
def->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT;
}
- if (source == NULL) {
+ if (source == NULL &&
+ def->type != VIR_DOMAIN_FS_TYPE_RAM) {
virDomainReportError(VIR_ERR_NO_SOURCE,
target ? "%s" : NULL, target);
goto error;
@@ -4309,6 +4312,16 @@ virDomainFSDefParseXML(xmlNodePtr node,
goto error;
}
+ if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
+ def->usage = VIR_DOMAIN_FS_RAM_DEFAULT_USAGE;
+ if (virDomainParseScaledValue("./source[0]", ctxt,
+ &def->usage,
+ 1024,
+ ULONG_LONG_MAX,
+ false) < 0)
+ goto error;
+ }
+
def->src = source;
source = NULL;
def->dst = target;
@@ -4325,6 +4338,7 @@ cleanup:
VIR_FREE(source);
VIR_FREE(accessmode);
VIR_FREE(wrpolicy);
+ VIR_FREE(usage);
return def;
@@ -11319,27 +11333,31 @@ virDomainFSDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
- if (def->src) {
- switch (def->type) {
- case VIR_DOMAIN_FS_TYPE_MOUNT:
- virBufferEscapeString(buf, " <source
dir='%s'/>\n",
- def->src);
- break;
+ switch (def->type) {
+ case VIR_DOMAIN_FS_TYPE_MOUNT:
+ virBufferEscapeString(buf, " <source dir='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_BLOCK:
- virBufferEscapeString(buf, " <source
dev='%s'/>\n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_BLOCK:
+ virBufferEscapeString(buf, " <source dev='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_FILE:
- virBufferEscapeString(buf, " <source
file='%s'/>\n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_FILE:
+ virBufferEscapeString(buf, " <source
file='%s'/>\n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_TEMPLATE:
- virBufferEscapeString(buf, " <source
name='%s'/>\n",
- def->src);
- }
+ case VIR_DOMAIN_FS_TYPE_TEMPLATE:
+ virBufferEscapeString(buf, " <source
name='%s'/>\n",
+ def->src);
+ break;
+
+ case VIR_DOMAIN_FS_TYPE_RAM:
+ virBufferAsprintf(buf, " <source usage='%lld'
units='KiB'/>\n",
+ def->usage);
+ break;
}
virBufferEscapeString(buf, " <target dir='%s'/>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 86c1e63..b8d9c87 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -660,6 +660,7 @@ enum virDomainFSType {
VIR_DOMAIN_FS_TYPE_BLOCK,
VIR_DOMAIN_FS_TYPE_FILE,
VIR_DOMAIN_FS_TYPE_TEMPLATE,
+ VIR_DOMAIN_FS_TYPE_RAM,
VIR_DOMAIN_FS_TYPE_LAST
};
@@ -690,11 +691,15 @@ enum virDomainFSWrpolicy {
VIR_DOMAIN_FS_WRPOLICY_LAST
};
+/* Allow 2 MB ram usage */
+#define VIR_DOMAIN_FS_RAM_DEFAULT_USAGE (1024 * 2)
+
struct _virDomainFSDef {
int type;
int fsdriver;
int accessmode;
int wrpolicy; /* enum virDomainFSWrpolicy */
+ unsigned long long usage;
char *src;
char *dst;
unsigned int readonly : 1;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 24b1017..b69255e 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -335,6 +335,8 @@ static int lxcContainerPivotRoot(virDomainFSDefPtr root)
ret = -1;
+ VIR_DEBUG("Pivot via %s", root->src);
+
/* root->parent must be private, so make / private. */
if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
virReportSystemError(errno, "%s",
@@ -966,6 +968,47 @@ cleanup:
}
+static int lxcContainerMountFSTmpfs(virDomainFSDefPtr fs)
+{
+ int ret = -1;
+ char *data = NULL;
+
+ if (virAsprintf(&data, "size=%lldk", fs->usage) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virFileMakePath(fs->dst) < 0) {
+ virReportSystemError(errno,
+ _("Failed to create %s"),
+ fs->dst);
+ goto cleanup;
+ }
+
+ if (mount("tmpfs", fs->dst, "tmpfs", MS_NOSUID|MS_NODEV, data)
< 0) {
+ virReportSystemError(errno,
+ _("Failed to mount directory %s as tmpfs"),
+ fs->dst);
+ goto cleanup;
+ }
+
+ if (fs->readonly) {
+ VIR_DEBUG("Binding %s readonly", fs->dst);
+ if (mount(fs->dst, fs->dst, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) <
0) {
+ virReportSystemError(errno,
+ _("Failed to make directory %s readonly"),
+ fs->dst);
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(data);
+ return ret;
+}
+
+
static int lxcContainerMountFS(virDomainFSDefPtr fs,
const char *srcprefix)
{
@@ -978,6 +1021,10 @@ static int lxcContainerMountFS(virDomainFSDefPtr fs,
if (lxcContainerMountFSBlock(fs, srcprefix) < 0)
return -1;
break;
+ case VIR_DOMAIN_FS_TYPE_RAM:
+ if (lxcContainerMountFSTmpfs(fs) < 0)
+ return -1;
+ break;
case VIR_DOMAIN_FS_TYPE_FILE:
lxcError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected filesystem type %s"),
@@ -1441,6 +1488,8 @@ static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
for (i = 0 ; i < vmDef->nfss ; i++) {
virDomainFSDefPtr fs = vmDef->fss[i];
+ if (!fs->src)
+ continue;
if (virFileResolveAllLinks(fs->src, &newroot) < 0)
return -1;
--
1.7.10.2