From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list