[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [v7 PATCH 07/10] libxl: get and set soft affinity
Make space for two new cpumap-s, one in vcpu_info (for getting soft affinity) and build_info (for setting it) and amend the API for setting vCPU affinity. libxl_set_vcpuaffinity() now takes two cpumaps, one for hard and one for soft affinity (LIBXL_API_VERSION is exploited to retain source level backword compatibility). Either of the two cpumap can be NULL, in which case, only the affinity corresponding to the non-NULL cpumap will be affected. Getting soft affinity happens indirectly, via `xl vcpu-list' (as it is already for hard affinity). This commit also introduces some logic to check whether the affinity which will be used by Xen to schedule the vCPU(s) does actually match with the cpumaps provided. In fact, we want to allow every possible combination of hard and soft affinity to be set, but we warn the user upon particularly weird situations (e.g., hard and soft being disjoint sets of pCPUs). This very change also update the error handling for calls to libxl_set_vcpuaffinity() in xl, as that can now be any libxl error code, not just only -1. Signed-off-by: Dario Faggioli <dario.faggioli@xxxxxxxxxx> Reviewed-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx> --- Changes from v6: * fix a typo and update LIBXL_API_VERSION appropriately, as requested during review; * libxl_bitmap_equal() rewritten in such a way that it now automatically deals with bitmaps of different sizes. Bits non present in one of the maps are just considered to be 0, as suggested during review; * there is no need for libxl_bitmap_bit_valid() any longer, so killed it; * inside libxl, retrieve and set both hard and soft affinity atomically, in just one call (to xc_vcpu_getaffinity() and xc_vcpu_setaffinity(), respectively), as requested during review. * update the changelog about changing the error handling for the call to libxl_set_vcpuaffinity() in xl. Changes from v4: * get rid of inline stubs inside the LIBXL_API_VERSION_XXX block and just use define, as suggested during review * adapt to the new xc interface; * avoid leaking cpumap_soft in libxl_list_vcpu on error, as requested during review; * fix bogous `return 0' in libxl_set_vcpuaffinity, as requested during review; * clarify the comment for LIBXL_HAVE_SOFT_AFFINITY, as suggested during review; * renamed libxl_bitmap_valid() to libxl_bitmap_bit_valid(), as suggested uring review. Changes from v3: * only introduce one LIBXL_HAVE_ symbol for soft affinity, as requested during review; * use LIBXL_API_VERSION instead of having multiple version of the same function, as suggested during review; * use libxl_get_nr_cpus() rather than libxl_get_cputopology(), as suggested during review; * use LOGE() instead of LIBXL__LOG_ERRNO(), as requested during review; * kill the flags and use just one _set_vcpuaffinity() function with two cpumaps, allowing either of them to be NULL, as suggested during review; * avoid overflowing the bitmaps in libxl_bitmap_equal(), as suggested during review. Changes from v2: * interface completely redesigned, as discussed during review. --- tools/libxl/libxl.c | 99 ++++++++++++++++++++++++++++++++++++++----- tools/libxl/libxl.h | 26 ++++++++++- tools/libxl/libxl_create.c | 6 +++ tools/libxl/libxl_dom.c | 3 + tools/libxl/libxl_types.idl | 4 +- tools/libxl/libxl_utils.h | 25 +++++++++++ tools/libxl/xl_cmdimpl.c | 6 +-- 7 files changed, 150 insertions(+), 19 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index ec79645..2cb7174 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -4577,13 +4577,17 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid, libxl_bitmap_init(&ptr->cpumap); if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap, 0)) goto err; + libxl_bitmap_init(&ptr->cpumap_soft); + if (libxl_cpu_bitmap_alloc(ctx, &ptr->cpumap_soft, 0)) + goto err; if (xc_vcpu_getinfo(ctx->xch, domid, *nr_vcpus_out, &vcpuinfo) == -1) { LOGE(ERROR, "getting vcpu info"); goto err; } + if (xc_vcpu_getaffinity(ctx->xch, domid, *nr_vcpus_out, - ptr->cpumap.map, NULL, - XEN_VCPUAFFINITY_HARD) == -1) { + ptr->cpumap.map, ptr->cpumap_soft.map, + XEN_VCPUAFFINITY_SOFT|XEN_VCPUAFFINITY_HARD) == -1) { LOGE(ERROR, "getting vcpu affinity"); goto err; } @@ -4599,34 +4603,105 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid, err: libxl_bitmap_dispose(&ptr->cpumap); + libxl_bitmap_dispose(&ptr->cpumap_soft); free(ret); GC_FREE; return NULL; } int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid, - libxl_bitmap *cpumap) + const libxl_bitmap *cpumap_hard, + const libxl_bitmap *cpumap_soft) { - if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap->map, NULL, - XEN_VCPUAFFINITY_HARD)) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity"); - return ERROR_FAIL; + GC_INIT(ctx); + libxl_bitmap hard, soft; + int rc, flags = 0; + + libxl_bitmap_init(&hard); + libxl_bitmap_init(&soft); + + if (!cpumap_hard && !cpumap_soft) { + rc = ERROR_INVAL; + goto out; } - return 0; + + /* + * Xen wants writable hard and/or soft cpumaps, to put back in them + * the effective hard and/or soft affinity that will be used. + */ + if (cpumap_hard) { + rc = libxl_cpu_bitmap_alloc(ctx, &hard, 0); + if (rc) + goto out; + + libxl_bitmap_copy(ctx, &hard, cpumap_hard); + flags = XEN_VCPUAFFINITY_HARD; + } + if (cpumap_soft) { + rc = libxl_cpu_bitmap_alloc(ctx, &soft, 0); + if (rc) + goto out; + + libxl_bitmap_copy(ctx, &soft, cpumap_soft); + flags |= XEN_VCPUAFFINITY_SOFT; + } + + if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, + cpumap_hard ? hard.map : NULL, + cpumap_soft ? soft.map : NULL, + flags)) { + LOGE(ERROR, "setting vcpu affinity"); + rc = ERROR_FAIL; + goto out; + } + + /* + * Let's check the results. Hard affinity will never be empty, but it + * is possible that Xen will use something different from what we asked + * for various reasons. If that's the case, report it. + */ + if (cpumap_hard && + !libxl_bitmap_equal(cpumap_hard, &hard, 0)) + LOG(DEBUG, "New hard affinity for vcpu %d has unreachable cpus", + vcpuid); + /* + * Soft affinity can both be different from what asked and empty. Check + * for (and report) both. + */ + if (cpumap_soft) { + if (!libxl_bitmap_equal(cpumap_soft, &soft, 0)) + LOG(DEBUG, "New soft affinity for vcpu %d has unreachable cpus", + vcpuid); + if (libxl_bitmap_is_empty(&soft)) + LOG(WARN, "all cpus in soft affinity of vcpu %d are unreachable." + " Only hard affinity will be considered for scheduling", + vcpuid); + } + + rc = 0; + out: + libxl_bitmap_dispose(&hard); + libxl_bitmap_dispose(&soft); + GC_FREE; + return rc; } int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid, - unsigned int max_vcpus, libxl_bitmap *cpumap) + unsigned int max_vcpus, + const libxl_bitmap *cpumap_hard, + const libxl_bitmap *cpumap_soft) { + GC_INIT(ctx); int i, rc = 0; for (i = 0; i < max_vcpus; i++) { - if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap)) { - LIBXL__LOG(ctx, LIBXL__LOG_WARNING, - "failed to set affinity for %d", i); + if (libxl_set_vcpuaffinity(ctx, domid, i, cpumap_hard, cpumap_soft)) { + LOG(WARN, "failed to set affinity for %d", i); rc = ERROR_FAIL; } } + + GC_FREE; return rc; } diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 80947c3..e549db8 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -82,6 +82,15 @@ #define LIBXL_HAVE_DOMAIN_NODEAFFINITY 1 /* + * LIBXL_HAVE_SOFT_AFFINITY indicates that a 'cpumap_soft' + * field (of libxl_bitmap type) is present in: + * - libxl_vcpuinfo, containing the soft affinity of a vcpu; + * - libxl_domain_build_info, for setting the soft affinity of + * all vcpus while creating the domain. + */ +#define LIBXL_HAVE_SOFT_AFFINITY 1 + +/* * LIBXL_HAVE_BUILDINFO_HVM_VENDOR_DEVICE indicates that the * libxl_vendor_device field is present in the hvm sections of * libxl_domain_build_info. This field tells libxl which @@ -1097,9 +1106,22 @@ int libxl_userdata_retrieve(libxl_ctx *ctx, uint32_t domid, int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo); int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid, - libxl_bitmap *cpumap); + const libxl_bitmap *cpumap_hard, + const libxl_bitmap *cpumap_soft); int libxl_set_vcpuaffinity_all(libxl_ctx *ctx, uint32_t domid, - unsigned int max_vcpus, libxl_bitmap *cpumap); + unsigned int max_vcpus, + const libxl_bitmap *cpumap_hard, + const libxl_bitmap *cpumap_soft); + +#if defined (LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x040500 + +#define libxl_set_vcpuaffinity(ctx, domid, vcpuid, map) \ + libxl_set_vcpuaffinity((ctx), (domid), (vcpuid), (map), NULL) +#define libxl_set_vcpuaffinity_all(ctx, domid, max_vcpus, map) \ + libxl_set_vcpuaffinity_all((ctx), (domid), (max_vcpus), (map), NULL) + +#endif + int libxl_domain_set_nodeaffinity(libxl_ctx *ctx, uint32_t domid, libxl_bitmap *nodemap); int libxl_domain_get_nodeaffinity(libxl_ctx *ctx, uint32_t domid, diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index d015cf4..49a01a7 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -193,6 +193,12 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc, libxl_bitmap_set_any(&b_info->cpumap); } + if (!b_info->cpumap_soft.size) { + if (libxl_cpu_bitmap_alloc(CTX, &b_info->cpumap_soft, 0)) + return ERROR_FAIL; + libxl_bitmap_set_any(&b_info->cpumap_soft); + } + libxl_defbool_setdefault(&b_info->numa_placement, true); if (!b_info->nodemap.size) { diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 661999c..91af7f8 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -261,7 +261,8 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid, return rc; } libxl_domain_set_nodeaffinity(ctx, domid, &info->nodemap); - libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus, &info->cpumap); + libxl_set_vcpuaffinity_all(ctx, domid, info->max_vcpus, &info->cpumap, + &info->cpumap_soft); if (xc_domain_setmaxmem(ctx->xch, domid, info->target_memkb + LIBXL_MAXMEM_CONSTANT) < 0) { diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 52f1aa9..15382cc 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -300,6 +300,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("max_vcpus", integer), ("avail_vcpus", libxl_bitmap), ("cpumap", libxl_bitmap), + ("cpumap_soft", libxl_bitmap), ("nodemap", libxl_bitmap), ("numa_placement", libxl_defbool), ("tsc_mode", libxl_tsc_mode), @@ -516,7 +517,8 @@ libxl_vcpuinfo = Struct("vcpuinfo", [ ("blocked", bool), ("running", bool), ("vcpu_time", uint64), # total vcpu time ran (ns) - ("cpumap", libxl_bitmap), # current cpu's affinities + ("cpumap", libxl_bitmap), # current hard cpu affinity + ("cpumap_soft", libxl_bitmap), # current soft cpu affinity ], dir=DIR_OUT) libxl_physinfo = Struct("physinfo", [ diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h index e37fb89..014f1f6 100644 --- a/tools/libxl/libxl_utils.h +++ b/tools/libxl/libxl_utils.h @@ -98,6 +98,31 @@ static inline int libxl_bitmap_cpu_valid(libxl_bitmap *bitmap, int bit) #define libxl_for_each_set_bit(v, m) for (v = 0; v < (m).size * 8; v++) \ if (libxl_bitmap_test(&(m), v)) +/* + * Compares two bitmaps bit by bit, up to nr_bits or, if nr_bits is 0, up + * to the size of the lagest bitmap. If sizes does not match, bits past the + * of a bitmap are considered as being 0, which matches with the semantic and + * implementation of libxl_bitmap_test I think(). + * + * So, basically, [0,1,0] and [0,1] are considered equal, while [0,1,1] and + * [0,1] are different. + */ +static inline int libxl_bitmap_equal(const libxl_bitmap *ba, + const libxl_bitmap *bb, + int nr_bits) +{ + int i; + + if (nr_bits == 0) + nr_bits = ba->size > bb->size ? ba->size * 8 : bb->size * 8; + + for (i = 0; i < nr_bits; i++) { + if (libxl_bitmap_test(ba, i) != libxl_bitmap_test(bb, i)) + return 0; + } + return 1; +} + int libxl_cpu_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *cpumap, int max_cpus); int libxl_node_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *nodemap, int max_nodes); diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 5195914..fa5ab8e 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -2269,7 +2269,7 @@ start: } else { libxl_bitmap_set_any(&vcpu_cpumap); } - if (libxl_set_vcpuaffinity(ctx, domid, i, &vcpu_cpumap)) { + if (libxl_set_vcpuaffinity(ctx, domid, i, &vcpu_cpumap, NULL)) { fprintf(stderr, "setting affinity failed on vcpu `%d'.\n", i); libxl_bitmap_dispose(&vcpu_cpumap); free(vcpu_to_pcpu); @@ -4700,7 +4700,7 @@ static int vcpupin(uint32_t domid, const char *vcpu, char *cpu) } if (vcpuid != -1) { - if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, &cpumap) == -1) { + if (libxl_set_vcpuaffinity(ctx, domid, vcpuid, &cpumap, NULL)) { fprintf(stderr, "Could not set affinity for vcpu `%u'.\n", vcpuid); goto out; } @@ -4712,7 +4712,7 @@ static int vcpupin(uint32_t domid, const char *vcpu, char *cpu) } for (i = 0; i < nb_vcpu; i++) { if (libxl_set_vcpuaffinity(ctx, domid, vcpuinfo[i].vcpuid, - &cpumap) == -1) { + &cpumap, NULL)) { fprintf(stderr, "libxl_set_vcpuaffinity failed" " on vcpu `%u'.\n", vcpuinfo[i].vcpuid); } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |