</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>
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>
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>
</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">
"mount",
"block",
"file",
- "template")
+ "template",
+ "ram")
VIR_ENUM_IMPL(virDomainFSDriverType, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
"default",
char *target = NULL;
char *accessmode = NULL;
char *wrpolicy = NULL;
+ char *usage = NULL;
+ char *unit = NULL;
ctxt->node = 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");
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;
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;
VIR_FREE(source);
VIR_FREE(accessmode);
VIR_FREE(wrpolicy);
+ VIR_FREE(usage);
+ VIR_FREE(unit);
return def;
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",
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
};
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;
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",
}
+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)
{
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"),
for (i = 0 ; i < vmDef->nfss ; i++) {
virDomainFSDefPtr fs = vmDef->fss[i];
+ if (!fs->src)
+ continue;
if (virFileResolveAllLinks(fs->src, &newroot) < 0)
return -1;