mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
Add support for RAM filesystems for LXC
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@redhat.com>
This commit is contained in:
parent
9c77bf04b0
commit
76b644c362
@ -1622,7 +1622,9 @@
|
||||
</dd>
|
||||
<dt><code>type='file'</code></dt>
|
||||
<dd>
|
||||
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.
|
||||
</dd>
|
||||
<dt><code>type='block'</code></dt>
|
||||
<dd>
|
||||
@ -1630,6 +1632,13 @@
|
||||
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. Only used
|
||||
by LXC driver.
|
||||
<span class="since"> (since 0.9.13)</span></dd>
|
||||
</dl>
|
||||
|
||||
The filesystem block has an optional attribute <code>accessmode</code>
|
||||
@ -1669,7 +1678,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>
|
||||
|
@ -1290,6 +1290,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">
|
||||
|
@ -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, " <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 / 1024);
|
||||
break;
|
||||
}
|
||||
|
||||
virBufferEscapeString(buf, " <target dir='%s'/>\n",
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user