[libvirt] [PATCH] Add support for RAM filesystems for LXC

Daniel Veillard veillard at redhat.com
Mon Jun 25 07:41:52 UTC 2012


On Fri, Jun 22, 2012 at 11:29:40AM +0100, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> 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 at redhat.com>
> ---
>  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.

  I would add "Only used by LXC driver" there too ...

> +          <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;
>  

  ACK with the small nit on documentation above,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list