Files
xen/tools/libs/light/libxl_cpupool.c
T
Juergen Gross 41aea82de2 tools/libxl: move libxenlight to tools/libs/light
Carve out all libxenlight related sources and move them to
tools/libs/light in order to use the generic library build environment.

The closely related sources for libxl-save-helper and the libxl test
environment are being moved, too.

Signed-off-by: Juergen Gross <jgross@suse.com>
Acked-by: Wei Liu <wl@xen.org>
2020-10-01 13:26:09 +02:00

453 lines
10 KiB
C

/*
* Copyright 2009-2017 Citrix Ltd and other contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#include "libxl_osdeps.h"
#include "libxl_internal.h"
/* Returns:
* 0 - success
* ERROR_FAIL + errno == ENOENT - no entry found
* ERROR_$FOO + errno != ENOENT - other failure
*/
static int cpupool_info(libxl__gc *gc,
libxl_cpupoolinfo *info,
uint32_t poolid,
bool exact /* exactly poolid or >= poolid */)
{
xc_cpupoolinfo_t *xcinfo;
int rc = ERROR_FAIL;
xcinfo = xc_cpupool_getinfo(CTX->xch, poolid);
if (xcinfo == NULL)
{
if (exact || errno != ENOENT)
LOGE(ERROR, "failed to get info for cpupool%d", poolid);
return ERROR_FAIL;
}
if (exact && xcinfo->cpupool_id != poolid)
{
LOG(ERROR, "got info for cpupool%d, wanted cpupool%d\n",
xcinfo->cpupool_id, poolid);
goto out;
}
info->poolid = xcinfo->cpupool_id;
info->pool_name = libxl_cpupoolid_to_name(CTX, info->poolid);
if (!info->pool_name) {
rc = ERROR_FAIL;
goto out;
}
info->sched = xcinfo->sched_id;
info->n_dom = xcinfo->n_dom;
rc = libxl_cpu_bitmap_alloc(CTX, &info->cpumap, 0);
if (rc)
goto out;
memcpy(info->cpumap.map, xcinfo->cpumap, info->cpumap.size);
rc = 0;
out:
xc_cpupool_infofree(CTX->xch, xcinfo);
return rc;
}
int libxl_cpupool_info(libxl_ctx *ctx,
libxl_cpupoolinfo *info, uint32_t poolid)
{
GC_INIT(ctx);
int rc = cpupool_info(gc, info, poolid, true);
GC_FREE;
return rc;
}
libxl_cpupoolinfo * libxl_list_cpupool(libxl_ctx *ctx, int *nb_pool_out)
{
GC_INIT(ctx);
libxl_cpupoolinfo info, *ptr;
int i;
uint32_t poolid;
ptr = NULL;
poolid = 0;
for (i = 0;; i++) {
libxl_cpupoolinfo_init(&info);
if (cpupool_info(gc, &info, poolid, false)) {
libxl_cpupoolinfo_dispose(&info);
if (errno != ENOENT) goto out;
break;
}
ptr = libxl__realloc(NOGC, ptr, (i+1) * sizeof(libxl_cpupoolinfo));
ptr[i] = info;
poolid = info.poolid + 1;
/* Don't dispose of info because it will be returned to caller */
}
*nb_pool_out = i;
GC_FREE;
return ptr;
out:
libxl_cpupoolinfo_list_free(ptr, i);
*nb_pool_out = 0;
GC_FREE;
return NULL;
}
int libxl_get_freecpus(libxl_ctx *ctx, libxl_bitmap *cpumap)
{
int ncpus;
ncpus = libxl_get_max_cpus(ctx);
if (ncpus < 0)
return ncpus;
cpumap->map = xc_cpupool_freeinfo(ctx->xch);
if (cpumap->map == NULL)
return ERROR_FAIL;
cpumap->size = (ncpus + 7) / 8;
return 0;
}
int libxl_cpupool_create(libxl_ctx *ctx, const char *name,
libxl_scheduler sched,
libxl_bitmap cpumap, libxl_uuid *uuid,
uint32_t *poolid)
{
GC_INIT(ctx);
int rc;
int i;
xs_transaction_t t;
char *uuid_string;
uint32_t xcpoolid;
/* Accept '0' as 'any poolid' for backwards compatibility */
if ( *poolid == LIBXL_CPUPOOL_POOLID_ANY
|| *poolid == 0 )
xcpoolid = XC_CPUPOOL_POOLID_ANY;
else
xcpoolid = *poolid;
uuid_string = libxl__uuid2string(gc, *uuid);
if (!uuid_string) {
GC_FREE;
return ERROR_NOMEM;
}
rc = xc_cpupool_create(ctx->xch, &xcpoolid, sched);
if (rc) {
LOGEV(ERROR, rc, "Could not create cpupool");
GC_FREE;
return ERROR_FAIL;
}
*poolid = xcpoolid;
libxl_for_each_bit(i, cpumap)
if (libxl_bitmap_test(&cpumap, i)) {
rc = xc_cpupool_addcpu(ctx->xch, *poolid, i);
if (rc) {
LOGEV(ERROR, rc, "Error moving cpu to cpupool");
libxl_cpupool_destroy(ctx, *poolid);
GC_FREE;
return ERROR_FAIL;
}
}
for (;;) {
t = xs_transaction_start(ctx->xsh);
xs_mkdir(ctx->xsh, t, GCSPRINTF("/local/pool/%d", *poolid));
libxl__xs_printf(gc, t,
GCSPRINTF("/local/pool/%d/uuid", *poolid),
"%s", uuid_string);
libxl__xs_printf(gc, t,
GCSPRINTF("/local/pool/%d/name", *poolid),
"%s", name);
if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN)) {
GC_FREE;
return 0;
}
}
}
int libxl_cpupool_destroy(libxl_ctx *ctx, uint32_t poolid)
{
GC_INIT(ctx);
int rc, i;
xc_cpupoolinfo_t *info;
xs_transaction_t t;
libxl_bitmap cpumap;
info = xc_cpupool_getinfo(ctx->xch, poolid);
if (info == NULL) {
GC_FREE;
return ERROR_NOMEM;
}
rc = ERROR_INVAL;
if ((info->cpupool_id != poolid) || (info->n_dom))
goto out;
rc = libxl_cpu_bitmap_alloc(ctx, &cpumap, 0);
if (rc)
goto out;
memcpy(cpumap.map, info->cpumap, cpumap.size);
libxl_for_each_bit(i, cpumap)
if (libxl_bitmap_test(&cpumap, i)) {
rc = xc_cpupool_removecpu(ctx->xch, poolid, i);
if (rc) {
LOGEV(ERROR, rc, "Error removing cpu from cpupool");
rc = ERROR_FAIL;
goto out1;
}
}
rc = xc_cpupool_destroy(ctx->xch, poolid);
if (rc) {
LOGEV(ERROR, rc, "Could not destroy cpupool");
rc = ERROR_FAIL;
goto out1;
}
for (;;) {
t = xs_transaction_start(ctx->xsh);
xs_rm(ctx->xsh, XBT_NULL, GCSPRINTF("/local/pool/%d", poolid));
if (xs_transaction_end(ctx->xsh, t, 0) || (errno != EAGAIN))
break;
}
rc = 0;
out1:
libxl_bitmap_dispose(&cpumap);
out:
xc_cpupool_infofree(ctx->xch, info);
GC_FREE;
return rc;
}
int libxl_cpupool_rename(libxl_ctx *ctx, const char *name, uint32_t poolid)
{
GC_INIT(ctx);
xs_transaction_t t;
xc_cpupoolinfo_t *info;
int rc;
info = xc_cpupool_getinfo(ctx->xch, poolid);
if (info == NULL) {
GC_FREE;
return ERROR_NOMEM;
}
rc = ERROR_INVAL;
if (info->cpupool_id != poolid)
goto out;
rc = 0;
for (;;) {
t = xs_transaction_start(ctx->xsh);
libxl__xs_printf(gc, t,
GCSPRINTF("/local/pool/%d/name", poolid),
"%s", name);
if (xs_transaction_end(ctx->xsh, t, 0))
break;
if (errno == EAGAIN)
continue;
rc = ERROR_FAIL;
break;
}
out:
xc_cpupool_infofree(ctx->xch, info);
GC_FREE;
return rc;
}
int libxl_cpupool_cpuadd(libxl_ctx *ctx, uint32_t poolid, int cpu)
{
GC_INIT(ctx);
int rc = 0;
rc = xc_cpupool_addcpu(ctx->xch, poolid, cpu);
if (rc) {
LOGE(ERROR, "Error moving cpu %d to cpupool", cpu);
rc = ERROR_FAIL;
}
GC_FREE;
return rc;
}
int libxl_cpupool_cpuadd_cpumap(libxl_ctx *ctx, uint32_t poolid,
const libxl_bitmap *cpumap)
{
int c, ncpus = 0, rc = 0;
libxl_for_each_set_bit(c, *cpumap) {
if (!libxl_cpupool_cpuadd(ctx, poolid, c))
ncpus++;
}
if (ncpus != libxl_bitmap_count_set(cpumap))
rc = ERROR_FAIL;
return rc;
}
int libxl_cpupool_cpuadd_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
{
int rc = 0;
int cpu, nr;
libxl_bitmap freemap;
libxl_cputopology *topology;
if (libxl_get_freecpus(ctx, &freemap)) {
return ERROR_FAIL;
}
topology = libxl_get_cpu_topology(ctx, &nr);
if (!topology) {
rc = ERROR_FAIL;
goto out;
}
*cpus = 0;
for (cpu = 0; cpu < nr; cpu++) {
if (libxl_bitmap_test(&freemap, cpu) && (topology[cpu].node == node) &&
!libxl_cpupool_cpuadd(ctx, poolid, cpu)) {
(*cpus)++;
}
libxl_cputopology_dispose(&topology[cpu]);
}
free(topology);
out:
libxl_bitmap_dispose(&freemap);
return rc;
}
int libxl_cpupool_cpuremove(libxl_ctx *ctx, uint32_t poolid, int cpu)
{
GC_INIT(ctx);
int rc = 0;
rc = xc_cpupool_removecpu(ctx->xch, poolid, cpu);
if (rc) {
LOGE(ERROR, "Error removing cpu %d from cpupool", cpu);
rc = ERROR_FAIL;
}
GC_FREE;
return rc;
}
int libxl_cpupool_cpuremove_cpumap(libxl_ctx *ctx, uint32_t poolid,
const libxl_bitmap *cpumap)
{
int c, ncpus = 0, rc = 0;
libxl_for_each_set_bit(c, *cpumap) {
if (!libxl_cpupool_cpuremove(ctx, poolid, c))
ncpus++;
}
if (ncpus != libxl_bitmap_count_set(cpumap))
rc = ERROR_FAIL;
return rc;
}
int libxl_cpupool_cpuremove_node(libxl_ctx *ctx, uint32_t poolid, int node, int *cpus)
{
int ret = 0;
int n_pools;
int p;
int cpu, nr_cpus;
libxl_cputopology *topology;
libxl_cpupoolinfo *poolinfo;
poolinfo = libxl_list_cpupool(ctx, &n_pools);
if (!poolinfo) {
return ERROR_NOMEM;
}
topology = libxl_get_cpu_topology(ctx, &nr_cpus);
if (!topology) {
ret = ERROR_FAIL;
goto out;
}
*cpus = 0;
for (p = 0; p < n_pools; p++) {
if (poolinfo[p].poolid == poolid) {
for (cpu = 0; cpu < nr_cpus; cpu++) {
if ((topology[cpu].node == node) &&
libxl_bitmap_test(&poolinfo[p].cpumap, cpu) &&
!libxl_cpupool_cpuremove(ctx, poolid, cpu)) {
(*cpus)++;
}
}
}
}
libxl_cputopology_list_free(topology, nr_cpus);
out:
libxl_cpupoolinfo_list_free(poolinfo, n_pools);
return ret;
}
int libxl_cpupool_movedomain(libxl_ctx *ctx, uint32_t poolid, uint32_t domid)
{
GC_INIT(ctx);
int rc;
rc = xc_cpupool_movedomain(ctx->xch, poolid, domid);
if (rc) {
LOGEVD(ERROR, rc, domid, "Error moving domain to cpupool");
GC_FREE;
return ERROR_FAIL;
}
GC_FREE;
return 0;
}
/*
* Local variables:
* mode: C
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/