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;