diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e1c0af5224..c13916ae2b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1622,7 +1622,9 @@
type='file'
- Currently unused.
+ A host file will be treated as an image and mounted in
+ the guest. The filesystem format will be autodetected.
+ Only used by LXC driver.
type='block'
@@ -1630,6 +1632,13 @@
format will be autodetected. Only used by LXC driver
(since 0.9.5) .
+ type='ram'
+
+ An in-memory filesystem, using memory from the host OS.
+ The source element has a single attribute usage
+ which gives the memory usage limit in kibibytes. Only used
+ by LXC driver.
+ (since 0.9.13)
The filesystem block has an optional attribute accessmode
@@ -1669,7 +1678,8 @@
The resource on the host that is being accessed in the guest. The
name
attribute must be used with
type='template'
, and the dir
attribute must
- be used with type='mount'
+ be used with type='mount'
. The usage
attribute
+ is used with type='ram'
to set the memory limit in KB.
target
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 86306252d8..7f0cfe89cf 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1290,6 +1290,24 @@
+
+
+ ram
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 46517652b8..774334068c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -264,7 +264,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",
@@ -4213,6 +4214,8 @@ virDomainFSDefParseXML(xmlNodePtr node,
char *target = NULL;
char *accessmode = NULL;
char *wrpolicy = NULL;
+ char *usage = NULL;
+ char *unit = NULL;
ctxt->node = node;
@@ -4269,6 +4272,10 @@ virDomainFSDefParseXML(xmlNodePtr node,
source = virXMLPropString(cur, "dev");
else if (def->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
source = virXMLPropString(cur, "name");
+ else if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
+ usage = virXMLPropString(cur, "usage");
+ unit = virXMLPropString(cur, "unit");
+ }
} else if (!target &&
xmlStrEqual(cur->name, BAD_CAST "target")) {
target = virXMLPropString(cur, "dir");
@@ -4300,7 +4307,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;
@@ -4312,6 +4320,25 @@ virDomainFSDefParseXML(xmlNodePtr node,
goto error;
}
+ if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
+ if (!usage) {
+ virDomainReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing 'usage' attribute for RAM filesystem"));
+ goto error;
+ }
+ if (virStrToLong_ull(usage, NULL, 10, &def->usage) < 0) {
+ virDomainReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse usage '%s' for RAM filesystem"),
+ usage);
+ goto error;
+ }
+ if (unit &&
+ virScaleInteger(&def->usage, unit,
+ 1024, ULONG_LONG_MAX) < 0)
+ goto error;
+ fprintf(stderr, "Useage %lld\n", def->usage);
+ }
+
def->src = source;
source = NULL;
def->dst = target;
@@ -4328,6 +4355,8 @@ cleanup:
VIR_FREE(source);
VIR_FREE(accessmode);
VIR_FREE(wrpolicy);
+ VIR_FREE(usage);
+ VIR_FREE(unit);
return def;
@@ -11322,27 +11351,31 @@ virDomainFSDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
- if (def->src) {
- switch (def->type) {
- case VIR_DOMAIN_FS_TYPE_MOUNT:
- virBufferEscapeString(buf, " \n",
- def->src);
- break;
+ switch (def->type) {
+ case VIR_DOMAIN_FS_TYPE_MOUNT:
+ virBufferEscapeString(buf, " \n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_BLOCK:
- virBufferEscapeString(buf, " \n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_BLOCK:
+ virBufferEscapeString(buf, " \n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_FILE:
- virBufferEscapeString(buf, " \n",
- def->src);
- break;
+ case VIR_DOMAIN_FS_TYPE_FILE:
+ virBufferEscapeString(buf, " \n",
+ def->src);
+ break;
- case VIR_DOMAIN_FS_TYPE_TEMPLATE:
- virBufferEscapeString(buf, " \n",
- def->src);
- }
+ case VIR_DOMAIN_FS_TYPE_TEMPLATE:
+ virBufferEscapeString(buf, " \n",
+ def->src);
+ break;
+
+ case VIR_DOMAIN_FS_TYPE_RAM:
+ virBufferAsprintf(buf, " \n",
+ def->usage / 1024);
+ break;
}
virBufferEscapeString(buf, " \n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 371278586c..7ce0694441 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -661,6 +661,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
};
@@ -691,11 +692,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 24b101735e..b69255e026 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;