[libvirt] [PATCH 1/5] Support NUMA memory placement for LXC containers

Daniel Veillard veillard at redhat.com
Thu Nov 24 13:49:51 UTC 2011


On Thu, Nov 24, 2011 at 11:38:12AM +0000, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> Use numactl to set NUMA memory placement for LXC containers
> 
> * src/lxc/lxc_controller.c: Support NUMA memory placement
> ---
>  src/lxc/lxc_controller.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 101 insertions(+), 0 deletions(-)
> 
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index 40047f0..4718fa8 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -48,6 +48,11 @@
>  # include <cap-ng.h>
>  #endif
>  
> +#if HAVE_NUMACTL
> +# define NUMA_VERSION1_COMPATIBILITY 1
> +# include <numa.h>
> +#endif
> +
>  #include "virterror_internal.h"
>  #include "logging.h"
>  #include "util.h"
> @@ -224,6 +229,99 @@ cleanup:
>      return ret;
>  }
>  
> +#if HAVE_NUMACTL
> +static int lxcSetContainerNUMAPolicy(virDomainDefPtr def)
> +{
> +    nodemask_t mask;
> +    int mode = -1;
> +    int node = -1;
> +    int ret = -1;
> +    int i = 0;
> +    int maxnode = 0;
> +    bool warned = false;
> +
> +    if (!def->numatune.memory.nodemask)
> +        return 0;
> +
> +    VIR_DEBUG("Setting NUMA memory policy");
> +
> +    if (numa_available() < 0) {
> +        lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                 "%s", _("Host kernel is not aware of NUMA."));
> +        return -1;
> +    }
> +
> +    maxnode = numa_max_node() + 1;
> +
> +    /* Convert nodemask to NUMA bitmask. */
> +    nodemask_zero(&mask);
> +    for (i = 0; i < VIR_DOMAIN_CPUMASK_LEN; i++) {
> +        if (def->numatune.memory.nodemask[i]) {
> +            if (i > NUMA_NUM_NODES) {
> +                lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                         _("Host cannot support NUMA node %d"), i);
> +                return -1;
> +            }
> +            if (i > maxnode && !warned) {
> +                VIR_WARN("nodeset is out of range, there is only %d NUMA "
> +                         "nodes on host", maxnode);
> +                warned = true;
> +             }

  small indent issue here

> +            nodemask_set(&mask, i);
> +        }
> +    }
> +
> +    mode = def->numatune.memory.mode;
> +
> +    if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
> +        numa_set_bind_policy(1);
> +        numa_set_membind(&mask);
> +        numa_set_bind_policy(0);
> +    } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) {
> +        int nnodes = 0;
> +        for (i = 0; i < NUMA_NUM_NODES; i++) {
> +            if (nodemask_isset(&mask, i)) {
> +                node = i;
> +                nnodes++;
> +            }
> +        }
> +
> +        if (nnodes != 1) {
> +            lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                     "%s", _("NUMA memory tuning in 'preferred' mode "
> +                             "only supports single node"));
> +            goto cleanup;
> +        }
> +
> +        numa_set_bind_policy(0);
> +        numa_set_preferred(node);
> +    } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) {
> +        numa_set_interleave_mask(&mask);
> +    } else {
> +        lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                 _("Unable to set NUMA policy %s"),
> +                 virDomainNumatuneMemModeTypeToString(mode));
> +        goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    return ret;
> +}
> +#else
> +static int lxcSetContainerNUMAPolicy(virDomainDefPtr def)
> +{
> +    if (def->numatune.memory.nodemask) {
> +        lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                 _("NUMA policy is not available on this platform"));
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +#endif
> +
>  /**
>   * lxcSetContainerResources
>   * @def: pointer to virtual machine structure
> @@ -249,6 +347,9 @@ static int lxcSetContainerResources(virDomainDefPtr def)
>          {'c', LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX},
>          {0,   0, 0}};
>  
> +    if (lxcSetContainerNUMAPolicy(def) < 0)
> +        return -1;
> +
>      rc = virCgroupForDriver("lxc", &driver, 1, 0);
>      if (rc != 0) {
>          /* Skip all if no driver cgroup is configured */

  ACK,

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