Signed-off-by: juergen.gross@xxxxxxxxxxxxxx Support of cpu pools in xl: library functions xl pool-create xl pool-list xl pool-destroy xl pool-cpu-add xl pool-cpu-remove xl pool-migrate diff -r d978675f3d53 tools/libxl/libxl.c --- a/tools/libxl/libxl.c Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxl.c Fri Sep 17 07:42:30 2010 +0200 @@ -609,9 +609,17 @@ libxl_poolinfo * libxl_list_pool(libxl_c libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool) { libxl_poolinfo *ptr; - int i, ret; - xc_cpupoolinfo_t info[256]; - int size = 256; + int i, m; + xc_cpupoolinfo_t *info; + int size; + uint32_t poolid; + libxl_physinfo physinfo; + + if (libxl_get_physinfo(ctx, &physinfo) != 0) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting phys info"); + return NULL; + } + size = physinfo.max_cpu_id + 32; ptr = calloc(size, sizeof(libxl_poolinfo)); if (!ptr) { @@ -619,16 +627,23 @@ libxl_poolinfo * libxl_list_pool(libxl_c return NULL; } - ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info); - if (ret<0) { - LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info"); - return NULL; + poolid = 0; + for (i = 0; i < size; i++) { + info = xc_cpupool_getinfo(ctx->xch, poolid); + if (info == NULL) + break; + ptr[i].poolid = info->cpupool_id; + ptr[i].sched_id = info->sched_id; + ptr[i].n_dom = info->n_dom; + if (libxl_cpumap_alloc(&ptr[i].cpumap, physinfo.max_cpu_id + 1)) + break; + for (m = 0; m < ptr[i].cpumap.size / sizeof(*ptr[i].cpumap.map); m++) + ptr[i].cpumap.map[m] = info->cpumap[m]; + poolid = info->cpupool_id + 1; + free(info); } - for (i = 0; i < ret; i++) { - ptr[i].poolid = info[i].cpupool_id; - } - *nb_pool = ret; + *nb_pool = i; return ptr; } @@ -2928,7 +2943,6 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ct xc_domaininfo_t domaininfo; xc_vcpuinfo_t vcpuinfo; xc_physinfo_t physinfo = { 0 }; - unsigned num_cpuwords; if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting infolist"); @@ -2944,10 +2958,9 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ct return NULL; } - num_cpuwords = ((physinfo.max_cpu_id + 64) / 64); for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) { - ptr->cpumap = malloc(num_cpuwords * sizeof(*ptr->cpumap)); - if (!ptr->cpumap) { + if (libxl_cpumap_alloc(&ptr->cpumap, *nrcpus)) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpumap"); return NULL; } if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) { @@ -2955,7 +2968,7 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ct return NULL; } if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, - ptr->cpumap, ((*nrcpus) + 7) / 8) == -1) { + ptr->cpumap.map, ((*nrcpus) + 7) / 8) == -1) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu affinity"); return NULL; } @@ -3359,3 +3372,180 @@ void libxl_file_reference_destroy(libxl_ libxl__file_reference_unmap(f); free(f->path); } + +int libxl_get_freecpus(libxl_ctx *ctx, libxl_cpumap *cpumap) +{ + libxl_physinfo info; + int ret; + + if (libxl_get_physinfo(ctx, &info) != 0) + return ERROR_FAIL; + + ret = libxl_cpumap_alloc(cpumap, info.max_cpu_id + 1); + if (ret) + return ret; + + if (xc_cpupool_freeinfo(ctx->xch, cpumap->map, cpumap->size)) { + free(cpumap->map); + cpumap->map = NULL; + return ERROR_FAIL; + } + + return 0; +} + +int libxl_create_cpupool(libxl_ctx *ctx, char *name, int schedid, + libxl_cpumap cpumap, libxl_uuid *uuid, + uint32_t *poolid) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int rc; + int i; + xs_transaction_t t; + char *uuid_string; + + uuid_string = libxl__uuid2string(&gc, *uuid); + if (!uuid_string) + return ERROR_NOMEM; + + rc = xc_cpupool_create(ctx->xch, poolid, schedid); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Could not create cpupool"); + return ERROR_FAIL; + } + + for (i = 0; i < cpumap.size * 8; i++) + if (cpumap.map[i / 64] & (1L << (i % 64))) { + rc = xc_cpupool_addcpu(ctx->xch, *poolid, i); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Error moving cpu to cpupool"); + return ERROR_FAIL; + } + } + + for (;;) { + t = xs_transaction_start(ctx->xsh); + + xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/pool/%d", *poolid)); + libxl__xs_write(&gc, t, libxl__sprintf(&gc, "/local/pool/%d/uuid", *poolid), + uuid_string); + libxl__xs_write(&gc, t, libxl__sprintf(&gc, "/local/pool/%d/name", *poolid), + name); + + if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) + return 0; + } +} + +int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int rc, i; + xc_cpupoolinfo_t *info; + xs_transaction_t t; + + info = xc_cpupool_getinfo(ctx->xch, poolid); + if (info == NULL) + return ERROR_NOMEM; + + rc = ERROR_INVAL; + if ((info->cpupool_id != poolid) || (info->n_dom)) + goto out; + + for (i = 0; i < info->cpumap_size; i++) + if (info->cpumap[i / 64] & (1L << (i % 64))) { + rc = xc_cpupool_removecpu(ctx->xch, poolid, i); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Error removing cpu from cpupool"); + rc = ERROR_FAIL; + goto out; + } + } + + rc = xc_cpupool_destroy(ctx->xch, poolid); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "Could not destroy cpupool"); + rc = ERROR_FAIL; + goto out; + } + + for (;;) { + t = xs_transaction_start(ctx->xsh); + + xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/pool/%d", poolid)); + + if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) + break; + } + + rc = 0; + +out: + free(info); + + return rc; +} + +int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu) +{ + int rc; + + rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Error moving cpu to cpupool"); + return ERROR_FAIL; + } + return 0; +} + +int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu) +{ + int rc; + + rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Error removing cpu from cpupool"); + return ERROR_FAIL; + } + return 0; +} + +int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid) +{ + libxl__gc gc = LIBXL_INIT_GC(ctx); + int rc; + char *dom_path; + char *vm_path; + char *poolname; + xs_transaction_t t; + + dom_path = libxl__xs_get_dompath(&gc, domid); + if (!dom_path) { + return ERROR_FAIL; + } + + rc = xc_cpupool_movedomain(ctx->xch, poolid, domid); + if (rc) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, + "Error moving domain to cpupool"); + return ERROR_FAIL; + } + + poolname = libxl__poolid_to_name(&gc, poolid); + vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path)); + for (; vm_path;) { + t = xs_transaction_start(ctx->xsh); + + libxl__xs_write(&gc, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), poolname); + + if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) + break; + } + + return 0; +} diff -r d978675f3d53 tools/libxl/libxl.h --- a/tools/libxl/libxl.h Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxl.h Fri Sep 17 07:42:30 2010 +0200 @@ -140,8 +140,6 @@ void libxl_string_list_destroy(libxl_str typedef char **libxl_key_value_list; void libxl_key_value_list_destroy(libxl_key_value_list *kvl); - -typedef uint64_t *libxl_cpumap; typedef uint32_t libxl_hwcap[8]; @@ -488,6 +486,15 @@ int libxl_device_net2_del(libxl_ctx *ctx int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait); +int libxl_get_freecpus(libxl_ctx *ctx, libxl_cpumap *cpumap); +int libxl_create_cpupool(libxl_ctx *ctx, char *name, int schedid, + libxl_cpumap cpumap, libxl_uuid *uuid, + uint32_t *poolid); +int libxl_destroy_cpupool(libxl_ctx *ctx, uint32_t poolid); +int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu); +int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu); +int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid); + /* common paths */ const char *libxl_sbindir_path(void); const char *libxl_bindir_path(void); diff -r d978675f3d53 tools/libxl/libxl.idl --- a/tools/libxl/libxl.idl Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxl.idl Fri Sep 17 07:42:30 2010 +0200 @@ -16,8 +16,6 @@ libxl_string_list = Builtin("string_list libxl_string_list = Builtin("string_list", destructor_fn="libxl_string_list_destroy", passby=PASS_BY_REFERENCE) libxl_key_value_list = Builtin("key_value_list", destructor_fn="libxl_key_value_list_destroy", passby=PASS_BY_REFERENCE) libxl_file_reference = Builtin("file_reference", destructor_fn="libxl_file_reference_destroy", passby=PASS_BY_REFERENCE) - -libxl_cpumap = Builtin("cpumap", destructor_fn="free") libxl_hwcap = Builtin("hwcap") @@ -44,9 +42,17 @@ SHUTDOWN_* constant."""), ("vcpu_online", uint32), ], destructor_fn=None) +libxl_cpumap = Struct("cpumap", [ + ("size", uint32, False, "number of bytes in map"), + ("map", Reference(uint64)), + ]) + libxl_poolinfo = Struct("poolinfo", [ - ("poolid", uint32) - ], destructor_fn=None) + ("poolid", uint32), + ("sched_id", uint32), + ("n_dom", uint32), + ("cpumap", libxl_cpumap) + ], destructor_fn="libxl_poolinfo_destroy") libxl_vminfo = Struct("vminfo", [ ("uuid", libxl_uuid), diff -r d978675f3d53 tools/libxl/libxl_utils.c --- a/tools/libxl/libxl_utils.c Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxl_utils.c Fri Sep 17 07:42:30 2010 +0200 @@ -31,6 +31,17 @@ #include "libxl_utils.h" #include "libxl_internal.h" +struct schedid_name { + char *name; + int id; +}; + +static struct schedid_name schedid_name[] = { + { "credit", XEN_SCHEDULER_CREDIT }, + { "sedf", XEN_SCHEDULER_SEDF }, + { "credit2", XEN_SCHEDULER_CREDIT2 }, + { NULL, -1 } +}; unsigned long libxl_get_required_shadow_memory(unsigned long maxmem_kb, unsigned int smp_cpus) { @@ -124,19 +135,41 @@ int libxl_name_to_poolid(libxl_ctx *ctx, return ERROR_NOMEM; for (i = 0; i < nb_pools; i++) { - poolname = libxl_poolid_to_name(ctx, poolinfo[i].poolid); - if (!poolname) - continue; - if (strcmp(poolname, name) == 0) { - *poolid = poolinfo[i].poolid; - ret = 0; + if (ret && ((poolname = libxl_poolid_to_name(ctx, + poolinfo[i].poolid)) != NULL)) { + if (strcmp(poolname, name) == 0) { + *poolid = poolinfo[i].poolid; + ret = 0; + free(poolname); + } free(poolname); - break; } - free(poolname); + libxl_poolinfo_destroy(poolinfo + i); } free(poolinfo); return ret; +} + +int libxl_name_to_schedid(libxl_ctx *ctx, const char *name) +{ + int i; + + for (i = 0; schedid_name[i].name != NULL; i++) + if (strcmp(name, schedid_name[i].name) == 0) + return schedid_name[i].id; + + return -1; +} + +char *libxl_schedid_to_name(libxl_ctx *ctx, int schedid) +{ + int i; + + for (i = 0; schedid_name[i].name != NULL; i++) + if (schedid_name[i].id == schedid) + return schedid_name[i].name; + + return "unknown"; } int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid) @@ -675,3 +708,36 @@ out: libxl__free_all(&gc); return rc; } + +int libxl_cpumap_alloc(libxl_cpumap *cpumap, int max_cpus) +{ + int elems; + + elems = (max_cpus + 63) / 64; + cpumap->map = calloc(elems, sizeof(*cpumap->map)); + if (!cpumap->map) + return ERROR_NOMEM; + cpumap->size = elems * 8; /* size in bytes */ + return 0; +} + +int libxl_cpumap_test(libxl_cpumap *cpumap, int cpu) +{ + if (cpu >= cpumap->size * 8) + return 0; + return (cpumap->map[cpu / 64] & (1L << (cpu & 63))) ? 1 : 0; +} + +void libxl_cpumap_set(libxl_cpumap *cpumap, int cpu) +{ + if (cpu >= cpumap->size * 8) + return; + cpumap->map[cpu / 64] |= 1L << (cpu & 63); +} + +void libxl_cpumap_reset(libxl_cpumap *cpumap, int cpu) +{ + if (cpu >= cpumap->size * 8) + return; + cpumap->map[cpu / 64] &= ~(1L << (cpu & 63)); +} diff -r d978675f3d53 tools/libxl/libxl_utils.h --- a/tools/libxl/libxl_utils.h Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxl_utils.h Fri Sep 17 07:42:30 2010 +0200 @@ -23,6 +23,8 @@ char *libxl_domid_to_name(libxl_ctx *ctx char *libxl_domid_to_name(libxl_ctx *ctx, uint32_t domid); int libxl_name_to_poolid(libxl_ctx *ctx, const char *name, uint32_t *poolid); char *libxl_poolid_to_name(libxl_ctx *ctx, uint32_t poolid); +int libxl_name_to_schedid(libxl_ctx *ctx, const char *name); +char *libxl_schedid_to_name(libxl_ctx *ctx, int schedid); int libxl_get_stubdom_id(libxl_ctx *ctx, int guest_domid); int libxl_is_stubdom(libxl_ctx *ctx, uint32_t domid, uint32_t *target_domid); int libxl_create_logfile(libxl_ctx *ctx, char *name, char **full_name); @@ -74,5 +76,9 @@ int libxl_devid_to_device_net2(libxl_ctx * return -1 if there are an error */ int libxl_check_device_model_version(libxl_ctx *ctx, char *path); +int libxl_cpumap_alloc(libxl_cpumap *cpumap, int max_cpus); +int libxl_cpumap_test(libxl_cpumap *cpumap, int cpu); +void libxl_cpumap_set(libxl_cpumap *cpumap, int cpu); +void libxl_cpumap_reset(libxl_cpumap *cpumap, int cpu); #endif diff -r d978675f3d53 tools/libxl/libxltypes.py --- a/tools/libxl/libxltypes.py Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/libxltypes.py Fri Sep 17 07:42:30 2010 +0200 @@ -131,7 +131,10 @@ class Reference(Type): kwargs.setdefault('passby', PASS_BY_VALUE) kwargs.setdefault('namespace', ty.namespace) - typename = ty.typename[len(kwargs['namespace']):] + + typename = ty.typename + if ty.namespace: + typename = typename[len(kwargs['namespace']):] Type.__init__(self, typename + " *", **kwargs) # diff -r d978675f3d53 tools/libxl/xl.h --- a/tools/libxl/xl.h Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/xl.h Fri Sep 17 07:42:30 2010 +0200 @@ -79,6 +79,12 @@ int main_network2attach(int argc, char * int main_network2attach(int argc, char **argv); int main_network2list(int argc, char **argv); int main_network2detach(int argc, char **argv); +int main_poolcreate(int argc, char **argv); +int main_poollist(int argc, char **argv); +int main_pooldestroy(int argc, char **argv); +int main_poolcpuadd(int argc, char **argv); +int main_poolcpuremove(int argc, char **argv); +int main_poolmigrate(int argc, char **argv); void help(char *command); diff -r d978675f3d53 tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/xl_cmdimpl.c Fri Sep 17 07:42:30 2010 +0200 @@ -421,7 +421,7 @@ static void printf_info(int domid, printf("\t(ssidref %d)\n", c_info->ssidref); printf("\t(name %s)\n", c_info->name); printf("\t(uuid " LIBXL_UUID_FMT ")\n", LIBXL_UUID_BYTES(c_info->uuid)); - printf("\t(cpupool %s (%d))\n", c_info->poolname, c_info->poolid); + printf("\t(cpupool %s)\n", c_info->poolname); if (c_info->xsdata) printf("\t(xsdata contains data)\n"); else @@ -3287,7 +3287,7 @@ static void print_vcpuinfo(uint32_t tdom printf("%9.1f ", ((float)vcpuinfo->vcpu_time / 1e9)); /* CPU AFFINITY */ pcpumap = nr_cpus > 64 ? (uint64_t)-1 : ((1ULL << nr_cpus) - 1); - for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) { + for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) { if (*cpumap < pcpumap) { break; } @@ -3302,7 +3302,7 @@ static void print_vcpuinfo(uint32_t tdom if (!nr_cpus) { printf("any cpu\n"); } else { - for (cpumap = vcpuinfo->cpumap; nr_cpus; ++cpumap) { + for (cpumap = vcpuinfo->cpumap.map; nr_cpus; ++cpumap) { pcpumap = *cpumap; for (i = 0; !(pcpumap & 1); ++i, pcpumap >>= 1) ; @@ -3574,10 +3574,7 @@ static void output_xeninfo(void) printf("xen_minor : %d\n", info->xen_version_minor); printf("xen_extra : %s\n", info->xen_version_extra); printf("xen_caps : %s\n", info->capabilities); - printf("xen_scheduler : %s\n", - sched_id == XEN_SCHEDULER_SEDF ? "sedf" : - sched_id == XEN_SCHEDULER_CREDIT ? "credit" : - sched_id == XEN_SCHEDULER_CREDIT2 ? "credit2" : "unknown"); + printf("xen_scheduler : %s\n", libxl_schedid_to_name(&ctx, sched_id)); printf("xen_pagesize : %lu\n", info->pagesize); printf("platform_params : virt_start=0x%lx\n", info->virt_start); printf("xen_changeset : %s\n", info->changeset); @@ -3608,6 +3605,8 @@ static void output_physinfo(void) libxl_physinfo info; const libxl_version_info *vinfo; unsigned int i; + libxl_cpumap cpumap; + int n = 0; if (libxl_get_physinfo(&ctx, &info) != 0) { fprintf(stderr, "libxl_physinfo failed.\n"); @@ -3634,6 +3633,13 @@ static void output_physinfo(void) printf("total_memory : %"PRIu64"\n", info.total_pages / i); printf("free_memory : %"PRIu64"\n", info.free_pages / i); } + if (!libxl_get_freecpus(&ctx, &cpumap)) { + for (i = 0; i < cpumap.size * 8; i++) + if (libxl_cpumap_test(&cpumap, i)) + n++; + printf("free_cpus : %d\n", n); + free(cpumap.map); + } return; } @@ -5049,3 +5055,444 @@ int main_tmem_freeable(int argc, char ** printf("%d\n", mb); return 0; } + +int main_poolcreate(int argc, char **argv) +{ + char *filename = NULL; + char *p, extra_config[1024]; + int dryrun = 0; + int opt; + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"defconfig", 1, 0, 'f'}, + {"dryrun", 0, 0, 'n'}, + {0, 0, 0, 0} + }; + int ret; + void *config_data = 0; + int config_len = 0; + XLU_Config *config; + const char *buf; + char *name, *sched; + uint32_t poolid; + int schedid = -1; + XLU_ConfigList *cpus; + int n_cpus, i, n; + libxl_cpumap freemap; + libxl_cpumap cpumap; + libxl_uuid uuid; + + while (1) { + opt = getopt_long(argc, argv, "hnf:", long_options, &option_index); + if (opt == -1) + break; + + switch (opt) { + case 'f': + filename = optarg; + break; + case 'h': + help("pool-create"); + return 0; + case 'n': + dryrun = 1; + break; + default: + fprintf(stderr, "option not supported\n"); + break; + } + } + + memset(extra_config, 0, sizeof(extra_config)); + while (optind < argc) { + if ((p = strchr(argv[optind], '='))) { + if (strlen(extra_config) + 1 < sizeof(extra_config)) { + if (strlen(extra_config)) + strcat(extra_config, "\n"); + strcat(extra_config, argv[optind]); + } + } else if (!filename) { + filename = argv[optind]; + } else { + help("pool-create"); + return -ERROR_FAIL; + } + optind++; + } + + if (!filename) { + help("pool-create"); + return -ERROR_FAIL; + } + + if (libxl_read_file_contents(&ctx, filename, &config_data, &config_len)) { + fprintf(stderr, "Failed to read config file: %s: %s\n", + filename, strerror(errno)); + return -ERROR_FAIL; + } + if (strlen(extra_config)) { + if (config_len > INT_MAX - (strlen(extra_config) + 2)) { + fprintf(stderr, "Failed to attach extra configration\n"); + return -ERROR_FAIL; + } + config_data = realloc(config_data, + config_len + strlen(extra_config) + 2); + if (!config_data) { + fprintf(stderr, "Failed to realloc config_data\n"); + return -ERROR_FAIL; + } + strcat(config_data, "\n"); + strcat(config_data, extra_config); + strcat(config_data, "\n"); + config_len += (strlen(extra_config) + 2); + } + + config = xlu_cfg_init(stderr, filename); + if (!config) { + fprintf(stderr, "Failed to allocate for configuration\n"); + return -ERROR_FAIL; + } + + ret = xlu_cfg_readdata(config, config_data, config_len); + if (ret) { + fprintf(stderr, "Failed to parse config file: %s\n", strerror(ret)); + return -ERROR_FAIL; + } + + if (!xlu_cfg_get_string (config, "name", &buf)) + name = strdup(buf); + else + name = basename(filename); + if (!libxl_name_to_poolid(&ctx, name, &poolid)) { + fprintf(stderr, "Pool name \"%s\" already exists\n", name); + return -ERROR_FAIL; + } + + if (!xlu_cfg_get_string (config, "sched", &buf)) { + if ((schedid = libxl_name_to_schedid(&ctx, buf)) < 0) { + fprintf(stderr, "Unknown scheduler\n"); + return -ERROR_FAIL; + } + } else { + if ((schedid = libxl_get_sched_id(&ctx)) < 0) { + fprintf(stderr, "get_sched_id sysctl failed.\n"); + return -ERROR_FAIL; + } + } + sched = libxl_schedid_to_name(&ctx, schedid); + + if (libxl_get_freecpus(&ctx, &freemap)) { + fprintf(stderr, "libxl_get_freecpus failed\n"); + return -ERROR_FAIL; + } + if (libxl_cpumap_alloc(&cpumap, freemap.size * 8)) { + fprintf(stderr, "Failed to allocate cpumap\n"); + return -ERROR_FAIL; + } + if (!xlu_cfg_get_list(config, "cpus", &cpus, 0)) { + n_cpus = 0; + while ((buf = xlu_cfg_get_listitem(cpus, n_cpus)) != NULL) { + i = atoi(buf); + if ((i < 0) || (i >= freemap.size * 8) || + !libxl_cpumap_test(&freemap, i)) { + fprintf(stderr, "cpu %d illegal or not free\n", i); + return -ERROR_FAIL; + } + libxl_cpumap_set(&cpumap, i); + n_cpus++; + } + } else { + n_cpus = 1; + n = 0; + for (i = 0; i < freemap.size; i++) + if (libxl_cpumap_test(&freemap, i)) { + n++; + libxl_cpumap_set(&cpumap, i); + break; + } + if (n != n_cpus) { + fprintf(stderr, "no free cpu found\n"); + return -ERROR_FAIL; + } + } + + libxl_uuid_generate(&uuid); + + printf("Using config file \"%s\"\n", filename); + printf("pool name: %s\n", name); + printf("scheduler: %s\n", sched); + printf("number of cpus: %d\n", n_cpus); + + if (dryrun) + return 0; + + poolid = 0; + if (libxl_create_cpupool(&ctx, name, schedid, cpumap, &uuid, &poolid)) { + fprintf(stderr, "error on creating cpupool\n"); + return -ERROR_FAIL; + } + + return 0; +} + +int main_poollist(int argc, char **argv) +{ + int opt; + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"long", 0, 0, 'l'}, + {"cpus", 0, 0, 'c'}, + {0, 0, 0, 0} + }; + int opt_long = 0; + int opt_cpus = 0; + char *pool = NULL; + libxl_poolinfo *poolinfo; + int n_pools, p, c, n; + uint32_t poolid; + char *name; + int ret = 0; + + while (1) { + opt = getopt_long(argc, argv, "hlc", long_options, &option_index); + if (opt == -1) + break; + + switch (opt) { + case 'h': + help("pool-list"); + return 0; + case 'l': + opt_long = 1; + break; + case 'c': + opt_cpus = 1; + break; + default: + fprintf(stderr, "option not supported\n"); + break; + } + } + + if ((optind + 1) < argc) { + help("pool-list"); + return -ERROR_FAIL; + } + if (optind < argc) { + pool = argv[optind]; + if (libxl_name_to_poolid(&ctx, pool, &poolid)) { + fprintf(stderr, "Pool \'%s\' does not exist\n", pool); + return -ERROR_FAIL; + } + } + + poolinfo = libxl_list_pool(&ctx, &n_pools); + if (!poolinfo) { + fprintf(stderr, "error getting cpupool info\n"); + return -ERROR_NOMEM; + } + + if (!opt_long) { + printf("%-19s", "Name"); + if (opt_cpus) + printf("CPU list\n"); + else + printf("CPUs Sched Active Domain count\n"); + } + + for (p = 0; p < n_pools; p++) { + if (!ret && (!pool || (poolinfo[p].poolid != poolid))) { + name = libxl_poolid_to_name(&ctx, poolinfo[p].poolid); + if (!name) { + fprintf(stderr, "error getting cpupool info\n"); + ret = -ERROR_NOMEM; + } + else if (opt_long) { + ret = -ERROR_NI; + } else { + printf("%-19s", name); + n = 0; + for (c = 0; c < poolinfo[p].cpumap.size * 8; c++) + if (poolinfo[p].cpumap.map[c / 64] & (1L << (c % 64))) { + if (n && opt_cpus) printf(","); + if (opt_cpus) printf("%d", c); + n++; + } + if (!opt_cpus) { + printf("%3d %9s y %4d", n, + libxl_schedid_to_name(&ctx, poolinfo[p].sched_id), + poolinfo[p].n_dom); + } + printf("\n"); + } + } + libxl_poolinfo_destroy(poolinfo + p); + } + + return ret; +} + +int main_pooldestroy(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-destroy"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-destroy"); + return -ERROR_FAIL; + } + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_destroy_cpupool(&ctx, poolid); +} + +int main_poolcpuadd(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + int cpu; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-cpu-add"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-cpu-add"); + return -ERROR_FAIL; + } + + if (!argv[optind]) { + fprintf(stderr, "no cpu specified\n"); + help("pool-cpu-add"); + return -ERROR_FAIL; + } + cpu = atoi(argv[optind]); + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_cpuadd(&ctx, poolid, cpu); +} + +int main_poolcpuremove(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + int cpu; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-cpu-remove"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-cpu-remove"); + return -ERROR_FAIL; + } + + if (!argv[optind]) { + fprintf(stderr, "no cpu specified\n"); + help("pool-cpu-remove"); + return -ERROR_FAIL; + } + cpu = atoi(argv[optind]); + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_cpuremove(&ctx, poolid, cpu); +} + +int main_poolmigrate(int argc, char **argv) +{ + int opt; + char *pool; + uint32_t poolid; + char *dom; + uint32_t domid; + + while ((opt = getopt(argc, argv, "h")) != -1) { + switch (opt) { + case 'h': + help("pool-migrate"); + return 0; + default: + fprintf(stderr, "option `%c' not supported.\n", opt); + break; + } + } + + dom = argv[optind++]; + if (!dom) { + fprintf(stderr, "no domain specified\n"); + help("pool-migrate"); + return -ERROR_FAIL; + } + + pool = argv[optind++]; + if (!pool) { + fprintf(stderr, "no cpupool specified\n"); + help("pool-migrate"); + return -ERROR_FAIL; + } + + if (domain_qualifier_to_domid(dom, &domid, NULL) || + !libxl_domid_to_name(&ctx, domid)) { + fprintf(stderr, "unknown domain \'%s\'\n", dom); + return -ERROR_FAIL; + } + + if (pool_qualifier_to_poolid(pool, &poolid, NULL) || + !libxl_poolid_to_name(&ctx, poolid)) { + fprintf(stderr, "unknown pool \'%s\'\n", pool); + return -ERROR_FAIL; + } + + return -libxl_cpupool_movedomain(&ctx, poolid, domid); +} diff -r d978675f3d53 tools/libxl/xl_cmdtable.c --- a/tools/libxl/xl_cmdtable.c Thu Sep 16 18:29:26 2010 +0100 +++ b/tools/libxl/xl_cmdtable.c Fri Sep 17 07:42:30 2010 +0200 @@ -338,6 +338,41 @@ struct cmd_spec cmd_table[] = { "destroy a domain's version 2 virtual network device", " ", }, + { "pool-create", + &main_poolcreate, + "Create a CPU pool based an ConfigFile", + "[options] [vars]", + "-h, --help Print this help.\n" + "-f=FILE, --defconfig=FILE Use the given configuration file.\n" + "-n, --dryrun Dry run - prints the resulting configuration." + }, + { "pool-list", + &main_poollist, + "List CPU pools on host", + "[-l|--long] [-c|--cpus] []", + "-l, --long Output all CPU pool details.\n" + "-c, --cpus Output list of CPUs used by a pool" + }, + { "pool-destroy", + &main_pooldestroy, + "Deactivates a CPU pool", + "", + }, + { "pool-cpu-add", + &main_poolcpuadd, + "Adds a CPU to a CPU pool", + " ", + }, + { "pool-cpu-remove", + &main_poolcpuremove, + "Removes a CPU from a CPU pool", + " ", + }, + { "pool-migrate", + &main_poolmigrate, + "Moves a domain into a CPU pool", + " ", + }, }; int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);