[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v10 8/9] libxl: vnuma nodes placement bits



On Wed, Sep 03, 2014 at 12:24:17AM -0400, Elena Ufimtseva wrote:
> Automatic numa placement cancels manual vnode placement
> mechanism. If numa placement explicitly specified, try
> to fit vnodes to the physical nodes.
> 
> Changes since v8:
>     - Addded number of ranges vmemranges for future support of
>       multi-range nodes; For PV guest it is set to same value
>       as number of vNUMA nodes.
> 

Three comments below. The errno values should have the default Exxx
(EINVAL, EAGAIN, etc), while the return should return ERROR_EINVAL, 
ERROR_BADFAIL,
ERROR_FAIL, etc (see  libxl_types.idl).


> Signed-off-by: Elena Ufimtseva <ufimtseva@xxxxxxxxx>
> ---
>  tools/libxl/libxl_create.c |    1 +
>  tools/libxl/libxl_dom.c    |  204 
> ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 205 insertions(+)
> 
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index fc332ef..a4977d2 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -203,6 +203,7 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
>      }
>  
>      libxl_defbool_setdefault(&b_info->numa_placement, true);
> +    libxl_defbool_setdefault(&b_info->vnuma_autoplacement, true);
>  
>      if (b_info->max_memkb == LIBXL_MEMKB_DEFAULT)
>          b_info->max_memkb = 32 * 1024;
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index c944804..b1376c4 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -23,6 +23,7 @@
>  #include <xc_dom.h>
>  #include <xen/hvm/hvm_info_table.h>
>  #include <xen/hvm/hvm_xs_strings.h>
> +#include <libxl_vnuma.h>
>  
>  libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
>  {
> @@ -227,12 +228,114 @@ static void hvm_set_conf_params(xc_interface *handle, 
> uint32_t domid,
>                      libxl_defbool_val(info->u.hvm.nested_hvm));
>  }
>  
> +/* sets vnode_to_pnode map. */
> +static int libxl__init_vnode_to_pnode(libxl__gc *gc, uint32_t domid,
> +                        libxl_domain_build_info *info)
> +{
> +    unsigned int i, n;
> +    int nr_nodes = 0;
> +    uint64_t *vnodes_mem;
> +    unsigned long long *nodes_claim = NULL;
> +    libxl_numainfo *ninfo = NULL;
> +
> +    if (info->vnuma_vnodemap == NULL) {
> +        info->vnuma_vnodemap = libxl__calloc(gc, info->vnodes,
> +                                      sizeof(*info->vnuma_vnodemap));
> +    }
> +
> +    /* default setting. */
> +    for (i = 0; i < info->vnodes; i++)
> +        info->vnuma_vnodemap[i] = LIBXC_VNUMA_NO_NODE;
> +
> +    /* Get NUMA info. */
> +    ninfo = libxl_get_numainfo(CTX, &nr_nodes);
> +    if (ninfo == NULL)
> +        return ERROR_FAIL;
> +    /* Nothing to see if only one NUMA node. */
> +    if (nr_nodes <= 1)
> +        return 0;
> +
> +    vnodes_mem = info->vnuma_mem;
> +    /*
> +     * TODO: change algorithm. The current just fits the nodes
> +     * by its memory sizes. If no p-node found, will be used default
> +     * value of LIBXC_VNUMA_NO_NODE.
> +     */
> +    nodes_claim = libxl__calloc(gc, info->vnodes, sizeof(*nodes_claim));
> +    if ( !nodes_claim )

A bit odd. The rest of the patch has a different style.

> +        return ERROR_FAIL;
> +
> +    libxl_for_each_set_bit(n, info->nodemap)
> +    {
> +        for (i = 0; i < info->vnodes; i++)
> +        {
> +            unsigned long mem_sz = vnodes_mem[i] << 20;
> +            if ((nodes_claim[n] + mem_sz <= ninfo[n].free) &&
> +                 /* vnode was not set yet. */
> +                 (info->vnuma_vnodemap[i] == LIBXC_VNUMA_NO_NODE ) )
> +            {
> +                info->vnuma_vnodemap[i] = n;
> +                nodes_claim[n] += mem_sz;
> +            }
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +/*
> + * Builds vnode memory regions from configuration info
> + * for vnuma nodes with multiple regions.
> + */
> +static int libxl__build_vnuma_ranges(libxl__gc *gc,
> +                              uint32_t domid,
> +                              /* IN: mem sizes in megabytes */
> +                              libxl_domain_build_info *b_info,
> +                              /* OUT: linux NUMA blocks addresses */
> +                              vmemrange_t **memrange)
> +{
> +    /*
> +     * For non-PV domains, contruction of the regions will
> +     * need to have its own implementation.
> +     */
> +    if (b_info->type != LIBXL_DOMAIN_TYPE_PV) {
> +        LOG(DETAIL, "vNUMA is only supported for PV guests now.\n");
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    if (b_info->vnodes == 0) {
> +        errno = EINVAL;
> +        return -1;

How come you return -1 here..
> +    }
> +
> +    b_info->vmemranges = b_info->vnodes;
> +
> +    *memrange = libxl__calloc(gc, b_info->vnodes,
> +                              sizeof(vmemrange_t));
> +
> +    /*
> +     * For PV domain along with alignment, regions nid will
> +     * be set to corresponding vnuma node number and ignored
> +     * later during allocation.
> +     */
> +
> +    if (libxl__vnuma_align_mem(gc, domid, b_info, *memrange) < 0) {
> +        LOG(DETAIL, "Failed to align memory map.\n");
> +        errno = ERROR_INVAL;

errno = EINVAL?

> +        return ERROR_FAIL;

.. but here you return ERROR_FAIL ?
> +    }
> +
> +    return 0;
> +}
> +
>  int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>                libxl_domain_config *d_config, libxl__domain_build_state 
> *state)
>  {
>      libxl_domain_build_info *const info = &d_config->b_info;
>      libxl_ctx *ctx = libxl__gc_owner(gc);
>      char *xs_domid, *con_domid;
> +    struct vmemrange *memrange;
>      int rc;
>  
>      if (xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus) != 0) {
> @@ -240,6 +343,20 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>          return ERROR_FAIL;
>      }
>  
> +    if (libxl__build_vnuma_ranges(gc, domid, info, &memrange) != 0) {
> +        LOG(DETAIL, "Failed to build vnuma nodes memory ranges.\n");
> +        return ERROR_FAIL;
> +
> +    }
> +
> +    /*
> +     * NUMA placement and vNUMA autoplacement handling:
> +     * If numa_placement is set to default, do not use vnode to pnode
> +     * mapping as automatic placement algorithm will find best numa nodes.
> +     * If numa_placement is not used, we can try and use domain vnode
> +     * to pnode mask.
> +     */
> +
>      /*
>       * Check if the domain has any CPU or node affinity already. If not, try
>       * to build up the latter via automatic NUMA placement. In fact, in case
> @@ -298,7 +415,33 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>                                     NULL, &cpumap_soft);
>  
>          libxl_bitmap_dispose(&cpumap_soft);
> +
> +        /*
> +         * If vnode_to_pnode mask was defined, dont use it if we 
> automatically
> +         * place domain on NUMA nodes, just give warning.
> +         */
> +        if (!libxl_defbool_val(info->vnuma_autoplacement)) {
> +            LOG(INFO, "Automatic NUMA placement for domain is turned on. \
> +                vnode to physical nodes mapping will not be used.");
> +        }
> +        if (libxl__init_vnode_to_pnode(gc, domid, info) < 0) {
> +            LOG(ERROR, "Failed to build vnode to pnode map\n");
> +            return ERROR_FAIL;
> +        }
> +    } else {
> +        if (!libxl_defbool_val(info->vnuma_autoplacement)) {
> +                if (!libxl__vnodemap_is_usable(gc, info)) {
> +                    LOG(ERROR, "Defined vnode to pnode domain map cannot be 
> used.\n");
> +                    return ERROR_FAIL;
> +                }
> +        } else {
> +            if (libxl__init_vnode_to_pnode(gc, domid, info) < 0) {
> +                LOG(ERROR, "Failed to build vnode to pnode map.\n");
> +                return ERROR_FAIL;
> +            }
> +        }
>      }
> +

Spurious.
>      if (info->nodemap.size)
>          libxl_domain_set_nodeaffinity(ctx, domid, &info->nodemap);
>      /* As mentioned in libxl.h, vcpu_hard_array takes precedence */
> @@ -339,6 +482,22 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>          return ERROR_FAIL;
>      }
>  
> +    /*
> +     * XEN_DOMCTL_setvnuma subop hypercall needs to know max mem
> +     * for domain set by xc_domain_setmaxmem. So set vNUMA after
> +     * maxmem is being set.
> +     * memrange should contain regions if multi-region nodes are
> +     * suppoted. For PV domain regions are ignored.
> +     */
> +    if (xc_domain_setvnuma(ctx->xch, domid, info->vnodes,
> +        info->vmemranges,
> +        info->max_vcpus, memrange,
> +        info->vdistance, info->vnuma_vcpumap,
> +        info->vnuma_vnodemap) < 0) {
> +        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't set vnuma 
> topology");
> +        return ERROR_FAIL;
> +    }
> +
>      xs_domid = xs_read(ctx->xsh, XBT_NULL, "/tool/xenstored/domid", NULL);
>      state->store_domid = xs_domid ? atoi(xs_domid) : 0;
>      free(xs_domid);
> @@ -434,6 +593,46 @@ retry_transaction:
>      return 0;
>  }
>  
> +/*
> + * Function fills the xc_dom_image with memory sizes for later
> + * use in domain memory allocator. No regions here are being
> + * filled and used in allocator as the regions do belong to one node.
> + */
> +static int libxl__dom_vnuma_init(struct libxl_domain_build_info *info,
> +                                 struct xc_dom_image *dom)
> +{
> +    errno = ERROR_INVAL;


Shouldnt that be EINVAL?

> +
> +    if (info->vnodes == 0)
> +        return -1;
> +
> +    info->vmemranges = info->vnodes;
> +
> +    dom->vnode_to_pnode = (unsigned int *)malloc(
> +                            info->vnodes * sizeof(*info->vnuma_vnodemap));
> +    dom->numa_memszs = (uint64_t *)malloc(
> +                          info->vnodes * sizeof(*info->vnuma_mem));
> +
> +    errno = ERROR_FAIL;
> +    if ( dom->numa_memszs == NULL || dom->vnode_to_pnode == NULL ) {
> +        info->vnodes = 0;
> +        if (dom->vnode_to_pnode)
> +            free(dom->vnode_to_pnode);
> +        if (dom->numa_memszs)
> +            free(dom->numa_memszs);
> +        return -1;

And this return ERROR_FAIL?

> +    }
> +
> +    memcpy(dom->numa_memszs, info->vnuma_mem,
> +            sizeof(*info->vnuma_mem) * info->vnodes);
> +    memcpy(dom->vnode_to_pnode, info->vnuma_vnodemap,
> +            sizeof(*info->vnuma_vnodemap) * info->vnodes);
> +
> +    dom->vnodes = info->vnodes;
> +
> +    return 0;
> +}
> +
>  int libxl__build_pv(libxl__gc *gc, uint32_t domid,
>               libxl_domain_build_info *info, libxl__domain_build_state *state)
>  {
> @@ -491,6 +690,11 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid,
>      dom->xenstore_domid = state->store_domid;
>      dom->claim_enabled = libxl_defbool_val(info->claim_mode);
>  
> +    if ( (ret = libxl__dom_vnuma_init(info, dom)) != 0 ) {
> +        LOGE(ERROR, "Failed to set doman vnuma");
> +        goto out;
> +    }
> +
>      if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) {
>          LOGE(ERROR, "xc_dom_boot_xen_init failed");
>          goto out;
> -- 
> 1.7.10.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.