Example #1
0
/* set cpus of a numa node in the bitmask */
static int
virCapabilitiesGetCpusForNode(virCapsPtr caps,
                              size_t node,
                              virBitmapPtr cpumask)
{
    virCapsHostNUMACellPtr cell = NULL;
    size_t cpu;
    size_t i;
    /* The numa node numbers can be non-contiguous. Ex: 0,1,16,17. */
    for (i = 0; i < caps->host.nnumaCell; i++) {
        if (caps->host.numaCell[i]->num == node) {
            cell = caps->host.numaCell[i];
            break;
        }
    }

    for (cpu = 0; cell && cpu < cell->ncpus; cpu++) {
        if (virBitmapSetBit(cpumask, cell->cpus[cpu].id) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Cpu '%u' in node '%zu' is out of range "
                             "of the provided bitmap"),
                           cell->cpus[cpu].id, node);
            return -1;
        }
    }

    return 0;
}
Example #2
0
int
virNumaGetNodeCPUs(int node,
                   virBitmapPtr *cpus)
{
    unsigned long *mask = NULL;
    unsigned long *allonesmask = NULL;
    virBitmapPtr cpumap = NULL;
    int ncpus = 0;
    int max_n_cpus = virNumaGetMaxCPUs();
    int mask_n_bytes = max_n_cpus / 8;
    size_t i;
    int ret = -1;

    *cpus = NULL;

    if (VIR_ALLOC_N(mask, mask_n_bytes / sizeof(*mask)) < 0)
        goto cleanup;

    if (VIR_ALLOC_N(allonesmask, mask_n_bytes / sizeof(*mask)) < 0)
        goto cleanup;

    memset(allonesmask, 0xff, mask_n_bytes);

    /* The first time this returns -1, ENOENT if node doesn't exist... */
    if (numa_node_to_cpus(node, mask, mask_n_bytes) < 0) {
        VIR_WARN("NUMA topology for cell %d is not available, ignoring", node);
        ret = -2;
        goto cleanup;
    }

    /* second, third... times it returns an all-1's mask */
    if (memcmp(mask, allonesmask, mask_n_bytes) == 0) {
        VIR_DEBUG("NUMA topology for cell %d is invalid, ignoring", node);
        ret = -2;
        goto cleanup;
    }

    if (!(cpumap = virBitmapNew(max_n_cpus)))
        goto cleanup;

    for (i = 0; i < max_n_cpus; i++) {
        if (MASK_CPU_ISSET(mask, i)) {
            ignore_value(virBitmapSetBit(cpumap, i));
            ncpus++;
        }
    }

    *cpus = cpumap;
    cpumap = NULL;
    ret = ncpus;

cleanup:
    VIR_FREE(mask);
    VIR_FREE(allonesmask);
    virBitmapFree(cpumap);

    return ret;
}
Example #3
0
/**
 * virNetDevMacVLanReserveID:
 *
 *  @id: id 0 - MACVLAN_MAX_ID+1 to reserve (or -1 for "first free")
 *  @flags: set VIR_NETDEV_MACVLAN_CREATE_WITH_TAP for macvtapN else macvlanN
 *  @quietFail: don't log an error if this name is already in-use
 *  @nextFree: reserve the next free ID *after* @id rather than @id itself
 *
 *  Reserve the indicated ID in the appropriate bitmap, or find the
 *  first free ID if @id is -1.
 *
 *  Returns newly reserved ID# on success, or -1 to indicate failure.
 */
static int
virNetDevMacVLanReserveID(int id, unsigned int flags,
                          bool quietFail, bool nextFree)
{
    virBitmapPtr bitmap;

    if (virNetDevMacVLanInitialize() < 0)
       return -1;

    bitmap = (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
        macvtapIDs :  macvlanIDs;

    if (id > MACVLAN_MAX_ID) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("can't use name %s%d - out of range 0-%d"),
                       (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
                       MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX,
                       id, MACVLAN_MAX_ID);
        return -1;
    }

    if ((id < 0 || nextFree) &&
        (id = virBitmapNextClearBit(bitmap, id)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("no unused %s names available"),
                       (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
                       MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX);
        return -1;
    }

    if (virBitmapIsBitSet(bitmap, id)) {
        if (quietFail) {
            VIR_INFO("couldn't reserve name %s%d - already in use",
                     (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
                     MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id);
        } else {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("couldn't reserve name %s%d - already in use"),
                           (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
                           MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id);
        }
        return -1;
    }

    if (virBitmapSetBit(bitmap, id) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("couldn't mark %s%d as used"),
                       (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
                       MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id);
        return -1;
    }

    VIR_INFO("reserving device %s%d",
             (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
             MACVTAP_NAME_PREFIX : MACVLAN_NAME_PREFIX, id);
    return id;
}
Example #4
0
static int
libxlNextFreeVncPort(libxlDriverPrivatePtr driver, int startPort)
{
    int i;

    for (i = startPort ; i < LIBXL_VNC_PORT_MAX; i++) {
        int fd;
        int reuse = 1;
        struct sockaddr_in addr;
        bool used = false;

        if (virBitmapGetBit(driver->reservedVNCPorts,
                            i - LIBXL_VNC_PORT_MIN, &used) < 0)
            VIR_DEBUG("virBitmapGetBit failed on bit %d", i - LIBXL_VNC_PORT_MIN);

        if (used)
            continue;

        addr.sin_family = AF_INET;
        addr.sin_port = htons(i);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        fd = socket(PF_INET, SOCK_STREAM, 0);
        if (fd < 0)
            return -1;

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)) < 0) {
            VIR_FORCE_CLOSE(fd);
            break;
        }

        if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
            /* Not in use, lets grab it */
            VIR_FORCE_CLOSE(fd);
            /* Add port to bitmap of reserved ports */
            if (virBitmapSetBit(driver->reservedVNCPorts,
                                i - LIBXL_VNC_PORT_MIN) < 0) {
                VIR_DEBUG("virBitmapSetBit failed on bit %d",
                          i - LIBXL_VNC_PORT_MIN);
            }
            return i;
        }
        VIR_FORCE_CLOSE(fd);

        if (errno == EADDRINUSE) {
            /* In use, try next */
            continue;
        }
        /* Some other bad failure, get out.. */
        break;
    }
    return -1;
}
Example #5
0
/* virDomainVirtioSerialAddrReserve
 *
 * Reserve the virtio serial address of the device
 *
 * For use with virDomainDeviceInfoIterate,
 * opaque should be the address set
 */
int
virDomainVirtioSerialAddrReserve(virDomainDefPtr def ATTRIBUTE_UNUSED,
                                 virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
                                 virDomainDeviceInfoPtr info,
                                 void *data)
{
    virDomainVirtioSerialAddrSetPtr addrs = data;
    char *str = NULL;
    int ret = -1;
    virBitmapPtr map = NULL;
    bool b;
    ssize_t i;

    if (!virDomainVirtioSerialAddrIsComplete(info))
        return 0;

    VIR_DEBUG("Reserving virtio serial %u %u", info->addr.vioserial.controller,
              info->addr.vioserial.port);

    i = virDomainVirtioSerialAddrFindController(addrs, info->addr.vioserial.controller);
    if (i < 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("virtio serial controller %u is missing"),
                       info->addr.vioserial.controller);
        goto cleanup;
    }

    map = addrs->controllers[i]->ports;
    if (virBitmapGetBit(map, info->addr.vioserial.port, &b) < 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("virtio serial controller %u does not have port %u"),
                       info->addr.vioserial.controller,
                       info->addr.vioserial.port);
        goto cleanup;
    }

    if (b) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("virtio serial port %u on controller %u is already occupied"),
                       info->addr.vioserial.port,
                       info->addr.vioserial.controller);
        goto cleanup;
    }

    ignore_value(virBitmapSetBit(map, info->addr.vioserial.port));

    ret = 0;

 cleanup:
    VIR_FREE(str);
    return ret;
}
Example #6
0
int virPortAllocatorAcquire(virPortAllocatorPtr pa,
                            unsigned short *port)
{
    int ret = -1;
    size_t i;

    *port = 0;
    virObjectLock(pa);

    for (i = pa->start; i <= pa->end && !*port; i++) {
        bool used = false, v6used = false;

        if (virBitmapGetBit(pa->bitmap,
                            i - pa->start, &used) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to query port %zu"), i);
            goto cleanup;
        }

        if (used)
            continue;

        if (virPortAllocatorBindToPort(&v6used, i, AF_INET6) < 0 ||
            virPortAllocatorBindToPort(&used, i, AF_INET) < 0)
            goto cleanup;

        if (!used && !v6used) {
            /* Add port to bitmap of reserved ports */
            if (virBitmapSetBit(pa->bitmap,
                                i - pa->start) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to reserve port %zu"), i);
                goto cleanup;
            }
            *port = i;
            ret = 0;
        }
    }

    if (*port == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to find an unused port in range '%s' (%d-%d)"),
                       pa->name, pa->start, pa->end);
    }
 cleanup:
    virObjectUnlock(pa);
    return ret;
}
Example #7
0
/*
 * Build  NUMA Toplogy with cell id starting from (0 + seq)
 * for testing
 */
static virCapsPtr
buildNUMATopology(int seq)
{
    virCapsPtr caps;
    virCapsHostNUMACellCPUPtr cell_cpus = NULL;
    int core_id, cell_id;
    int id;

    if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false)) == NULL)
        goto error;

    id = 0;
    for (cell_id = 0; cell_id < MAX_CELLS; cell_id++) {
        if (VIR_ALLOC_N(cell_cpus, MAX_CPUS_IN_CELL) < 0)
            goto error;

        for (core_id = 0; core_id < MAX_CPUS_IN_CELL; core_id++) {
            cell_cpus[core_id].id = id + core_id;
            cell_cpus[core_id].socket_id = cell_id + seq;
            cell_cpus[core_id].core_id = id + core_id;
            if (!(cell_cpus[core_id].siblings =
                  virBitmapNew(MAX_CPUS_IN_CELL)))
                goto error;
            ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id));
        }
        id++;

        if (virCapabilitiesAddHostNUMACell(caps, cell_id + seq,
                                           MAX_MEM_IN_CELL,
                                           MAX_CPUS_IN_CELL, cell_cpus,
                                           VIR_ARCH_NONE, NULL,
                                           VIR_ARCH_NONE, NULL) < 0)
           goto error;

        cell_cpus = NULL;
    }

    return caps;

 error:
    virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, MAX_CPUS_IN_CELL);
    VIR_FREE(cell_cpus);
    virObjectUnref(caps);
    return NULL;

}
/* set cpus of a numa node in the bitmask */
static int
virCapabilitiesGetCpusForNode(virCapsPtr caps,
                              size_t node,
                              virBitmapPtr cpumask)
{
    virCapsHostNUMACellPtr cell = caps->host.numaCell[node];
    size_t cpu;

    for (cpu = 0; cpu < cell->ncpus; cpu++) {
        if (virBitmapSetBit(cpumask, cell->cpus[cpu].id) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Cpu '%u' in node '%zu' is out of range "
                             "of the provided bitmap"),
                           cell->cpus[cpu].id, node);
            return -1;
        }
    }

    return 0;
}
Example #9
0
int
virPortAllocatorSetUsed(unsigned short port)
{
    int ret = -1;
    virPortAllocatorPtr pa = virPortAllocatorGet();

    if (!pa)
        return -1;

    virObjectLock(pa);

    if (virBitmapIsBitSet(pa->bitmap, port) ||
        virBitmapSetBit(pa->bitmap, port) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reserve port %d"), port);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virObjectUnlock(pa);
    return ret;
}
Example #10
0
virBitmapPtr
virProcessGetAffinity(pid_t pid)
{
    size_t i;
    cpuset_t mask;
    virBitmapPtr ret = NULL;

    CPU_ZERO(&mask);
    if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
                           sizeof(mask), &mask) != 0) {
        virReportSystemError(errno,
                             _("cannot get CPU affinity of process %d"), pid);
        return NULL;
    }

    if (!(ret = virBitmapNew(sizeof(mask) * 8)))
        return NULL;

    for (i = 0; i < sizeof(mask) * 8; i++)
        if (CPU_ISSET(i, &mask))
            ignore_value(virBitmapSetBit(ret, i));

    return ret;
}
Example #11
0
int virProcessGetAffinity(pid_t pid,
                          virBitmapPtr *map,
                          int maxcpu)
{
    size_t i;
    cpuset_t mask;

    if (!(*map = virBitmapNew(maxcpu)))
        return -1;

    CPU_ZERO(&mask);
    if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
                           sizeof(mask), &mask) != 0) {
        virReportSystemError(errno,
                             _("cannot get CPU affinity of process %d"), pid);
        return -1;
    }

    for (i = 0; i < maxcpu; i++)
        if (CPU_ISSET(i, &mask))
            ignore_value(virBitmapSetBit(*map, i));

    return 0;
}
Example #12
0
static int
libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps)
{
    libxl_numainfo *numa_info = NULL;
    libxl_cputopology *cpu_topo = NULL;
    int nr_nodes = 0, nr_cpus = 0;
    virCapsHostNUMACellCPUPtr *cpus = NULL;
    int *nr_cpus_node = NULL;
    size_t i;
    int ret = -1;

    /* Let's try to fetch all the topology information */
    numa_info = libxl_get_numainfo(ctx, &nr_nodes);
    if (numa_info == NULL || nr_nodes == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
    } else {
        cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus);
        if (cpu_topo == NULL || nr_cpus == 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxl_get_cpu_topology failed"));
            goto cleanup;
        }
    }

    if (VIR_ALLOC_N(cpus, nr_nodes) < 0)
        goto cleanup;

    if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0)
        goto cleanup;

    /* For each node, prepare a list of CPUs belonging to that node */
    for (i = 0; i < nr_cpus; i++) {
        int node = cpu_topo[i].node;

        if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
            continue;

        nr_cpus_node[node]++;

        if (nr_cpus_node[node] == 1) {
            if (VIR_ALLOC(cpus[node]) < 0)
                goto cleanup;
        } else {
            if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0)
                goto cleanup;
        }

        /* Mapping between what libxl tells and what libvirt wants */
        cpus[node][nr_cpus_node[node]-1].id = i;
        cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket;
        cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core;
        /* Allocate the siblings maps. We will be filling them later */
        cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus);
        if (!cpus[node][nr_cpus_node[node]-1].siblings) {
            virReportOOMError();
            goto cleanup;
        }
    }

    /* Let's now populate the siblings bitmaps */
    for (i = 0; i < nr_cpus; i++) {
        int node = cpu_topo[i].node;
        size_t j;

        if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
            continue;

        for (j = 0; j < nr_cpus_node[node]; j++) {
            if (cpus[node][j].socket_id == cpu_topo[i].socket &&
                cpus[node][j].core_id == cpu_topo[i].core)
                ignore_value(virBitmapSetBit(cpus[node][j].siblings, i));
        }
    }

    for (i = 0; i < nr_nodes; i++) {
        if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY)
            continue;

        if (virCapabilitiesAddHostNUMACell(caps, i, nr_cpus_node[i],
                                           numa_info[i].size / 1024,
                                           cpus[i]) < 0) {
            virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
                                                        nr_cpus_node[i]);
            goto cleanup;
        }

        /* This is safe, as the CPU list is now stored in the NUMA cell */
        cpus[i] = NULL;
    }

    ret = 0;

 cleanup:
    if (ret != 0) {
        for (i = 0; cpus && i < nr_nodes; i++)
            VIR_FREE(cpus[i]);
        virCapabilitiesFreeNUMAInfo(caps);
    }

    VIR_FREE(cpus);
    VIR_FREE(nr_cpus_node);
    libxl_cputopology_list_free(cpu_topo, nr_cpus);
    libxl_numainfo_list_free(numa_info, nr_nodes);

    return ret;
}
Example #13
0
int virProcessGetAffinity(pid_t pid,
                          virBitmapPtr *map,
                          int maxcpu)
{
    size_t i;
# ifdef CPU_ALLOC
    /* New method dynamically allocates cpu mask, allowing unlimted cpus */
    int numcpus = 1024;
    size_t masklen;
    cpu_set_t *mask;

    /* Not only may the statically allocated cpu_set_t be too small,
     * but there is no way to ask the kernel what size is large enough.
     * So you have no option but to pick a size, try, catch EINVAL,
     * enlarge, and re-try.
     *
     * http://lkml.org/lkml/2009/7/28/620
     */
 realloc:
    masklen = CPU_ALLOC_SIZE(numcpus);
    mask = CPU_ALLOC(numcpus);

    if (!mask) {
        virReportOOMError();
        return -1;
    }

    CPU_ZERO_S(masklen, mask);
    if (sched_getaffinity(pid, masklen, mask) < 0) {
        CPU_FREE(mask);
        if (errno == EINVAL &&
            numcpus < (1024 << 8)) { /* 262144 cpus ought to be enough for anyone */
            numcpus = numcpus << 2;
            goto realloc;
        }
        virReportSystemError(errno,
                             _("cannot get CPU affinity of process %d"), pid);
        return -1;
    }

    *map = virBitmapNew(maxcpu);
    if (!*map)
        return -1;

    for (i = 0; i < maxcpu; i++)
        if (CPU_ISSET_S(i, masklen, mask))
            ignore_value(virBitmapSetBit(*map, i));
    CPU_FREE(mask);
# else
    /* Legacy method uses a fixed size cpu mask, only allows up to 1024 cpus */
    cpu_set_t mask;

    CPU_ZERO(&mask);
    if (sched_getaffinity(pid, sizeof(mask), &mask) < 0) {
        virReportSystemError(errno,
                             _("cannot get CPU affinity of process %d"), pid);
        return -1;
    }

    for (i = 0; i < maxcpu; i++)
        if (CPU_ISSET(i, &mask))
            ignore_value(virBitmapSetBit(*map, i));
# endif

    return 0;
}
Example #14
0
static virCapsPtr
buildVirCapabilities(int max_cells,
                     int max_cpus_in_cell,
                     int max_mem_in_cell)
{
    virCapsPtr caps;
    virCapsHostNUMACellCPUPtr cell_cpus = NULL;
    virCapsHostNUMACellSiblingInfoPtr siblings = NULL;
    int core_id, cell_id, nsiblings;
    int id;
    size_t i;

    if ((caps = virCapabilitiesNew(VIR_ARCH_X86_64, 0, 0)) == NULL)
        goto error;

    id = 0;
    for (cell_id = 0; cell_id < max_cells; cell_id++) {
        if (VIR_ALLOC_N(cell_cpus, max_cpus_in_cell) < 0)
            goto error;

        for (core_id = 0; core_id < max_cpus_in_cell; core_id++) {
            cell_cpus[core_id].id = id;
            cell_cpus[core_id].socket_id = cell_id;
            cell_cpus[core_id].core_id = id + core_id;
            if (!(cell_cpus[core_id].siblings =
                  virBitmapNew(max_cpus_in_cell)))
                goto error;
            ignore_value(virBitmapSetBit(cell_cpus[core_id].siblings, id));
        }
        id++;

        if (VIR_ALLOC_N(siblings, max_cells) < 0)
            goto error;
        nsiblings = max_cells;

        for (i = 0; i < nsiblings; i++) {
            siblings[i].node = i;
            /* Some magical constants, see virNumaGetDistances()
             * for their description. */
            siblings[i].distance = cell_id == i ? 10 : 20;
        }

        if (virCapabilitiesAddHostNUMACell(caps, cell_id,
                                           max_mem_in_cell,
                                           max_cpus_in_cell, cell_cpus,
                                           nsiblings, siblings,
                                           0, NULL) < 0)
           goto error;

        cell_cpus = NULL;
        siblings = NULL;
    }

    return caps;

 error:
    virCapabilitiesClearHostNUMACellCPUTopology(cell_cpus, max_cpus_in_cell);
    VIR_FREE(cell_cpus);
    VIR_FREE(siblings);
    virObjectUnref(caps);
    return NULL;
}
Example #15
0
virHostCPUParseNode(const char *node,
                    virArch arch,
                    virBitmapPtr present_cpus_map,
                    virBitmapPtr online_cpus_map,
                    int threads_per_subcore,
                    int *sockets,
                    int *cores,
                    int *threads,
                    int *offline)
{
    /* Biggest value we can expect to be used as either socket id
     * or core id. Bitmaps will need to be sized accordingly */
    const int ID_MAX = 4095;
    int ret = -1;
    int processors = 0;
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    virBitmapPtr node_cpus_map = NULL;
    virBitmapPtr sockets_map = NULL;
    virBitmapPtr *cores_maps = NULL;
    int npresent_cpus = virBitmapSize(present_cpus_map);
    int sock_max = 0;
    int sock;
    int core;
    size_t i;
    int siblings;
    unsigned int cpu;
    int direrr;

    *threads = 0;
    *cores = 0;
    *sockets = 0;

    if (!(cpudir = opendir(node))) {
        virReportSystemError(errno, _("cannot opendir %s"), node);
        goto cleanup;
    }

    /* Keep track of the CPUs that belong to the current node */
    if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
        goto cleanup;

    /* enumerate sockets in the node */
    if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
        goto cleanup;

    while ((direrr = virDirRead(cpudir, &cpudirent, node)) > 0) {
        if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
            continue;

        if (!virBitmapIsBitSet(present_cpus_map, cpu))
            continue;

        /* Mark this CPU as part of the current node */
        if (virBitmapSetBit(node_cpus_map, cpu) < 0)
            goto cleanup;

        if (!virBitmapIsBitSet(online_cpus_map, cpu))
            continue;

        /* Parse socket */
        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
            goto cleanup;
        if (sock > ID_MAX) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Socket %d can't be handled (max socket is %d)"),
                           sock, ID_MAX);
            goto cleanup;
        }

        if (virBitmapSetBit(sockets_map, sock) < 0)
            goto cleanup;

        if (sock > sock_max)
            sock_max = sock;
    }

    if (direrr < 0)
        goto cleanup;

    sock_max++;

    /* allocate cores maps for each socket */
    if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
        goto cleanup;

    for (i = 0; i < sock_max; i++)
        if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
            goto cleanup;

    /* Iterate over all CPUs in the node, in ascending order */
    for (cpu = 0; cpu < npresent_cpus; cpu++) {

        /* Skip CPUs that are not part of the current node */
        if (!virBitmapIsBitSet(node_cpus_map, cpu))
            continue;

        if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
            if (threads_per_subcore > 0 &&
                cpu % threads_per_subcore != 0 &&
                virBitmapIsBitSet(online_cpus_map,
                                  cpu - (cpu % threads_per_subcore))) {
                /* Secondary offline threads are counted as online when
                 * subcores are in use and the corresponding primary
                 * thread is online */
                processors++;
            } else {
                /* But they are counted as offline otherwise */
                (*offline)++;
            }
            continue;
        }

        processors++;

        /* Parse socket */
        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
            goto cleanup;
        if (!virBitmapIsBitSet(sockets_map, sock)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("CPU socket topology has changed"));
            goto cleanup;
        }

        /* Parse core */
        if (ARCH_IS_S390(arch)) {
            /* logical cpu is equivalent to a core on s390 */
            core = cpu;
        } else {
            if ((core = virHostCPUGetValue(node, cpu,
                                           "topology/core_id", 0)) < 0)
                goto cleanup;
        }
        if (core > ID_MAX) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Core %d can't be handled (max core is %d)"),
                           core, ID_MAX);
            goto cleanup;
        }

        if (virBitmapSetBit(cores_maps[sock], core) < 0)
            goto cleanup;

        if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
            goto cleanup;

        if (siblings > *threads)
            *threads = siblings;
    }

    /* finalize the returned data */
    *sockets = virBitmapCountBits(sockets_map);

    for (i = 0; i < sock_max; i++) {
        if (!virBitmapIsBitSet(sockets_map, i))
            continue;

        core = virBitmapCountBits(cores_maps[i]);
        if (core > *cores)
            *cores = core;
    }

    if (threads_per_subcore > 0) {
        /* The thread count ignores offline threads, which means that only
         * only primary threads have been considered so far. If subcores
         * are in use, we need to also account for secondary threads */
        *threads *= threads_per_subcore;
    }
    ret = processors;

 cleanup:
    /* don't shadow a more serious error */
    if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
        virReportSystemError(errno, _("problem closing %s"), node);
        ret = -1;
    }
    if (cores_maps)
        for (i = 0; i < sock_max; i++)
            virBitmapFree(cores_maps[i]);
    VIR_FREE(cores_maps);
    virBitmapFree(sockets_map);
    virBitmapFree(node_cpus_map);

    return ret;
}
Example #16
0
/**
 * virBitmapParse:
 * @str: points to a string representing a human-readable bitmap
 * @terminator: character separating the bitmap to parse
 * @bitmap: a bitmap created from @str
 * @bitmapSize: the upper limit of num of bits in created bitmap
 *
 * This function is the counterpart of virBitmapFormat. This function creates
 * a bitmap, in which bits are set according to the content of @str.
 *
 * @str is a comma separated string of fields N, which means a number of bit
 * to set, and ^N, which means to unset the bit, and N-M for ranges of bits
 * to set.
 *
 * To allow parsing of bitmaps within larger strings it is possible to set
 * a termination character in the argument @terminator. When the character
 * in @terminator is encountered in @str, the parsing of the bitmap stops.
 * Pass 0 as @terminator if it is not needed. Whitespace characters may not
 * be used as terminators.
 *
 * Returns the number of bits set in @bitmap, or -1 in case of error.
 */
int
virBitmapParse(const char *str,
               char terminator,
               virBitmapPtr *bitmap,
               size_t bitmapSize)
{
    bool neg = false;
    const char *cur = str;
    char *tmp;
    size_t i;
    int start, last;

    if (!(*bitmap = virBitmapNew(bitmapSize)))
        return -1;

    if (!str)
        goto error;

    virSkipSpaces(&cur);

    if (*cur == '\0')
        goto error;

    while (*cur != 0 && *cur != terminator) {
        /*
         * 3 constructs are allowed:
         *     - N   : a single CPU number
         *     - N-M : a range of CPU numbers with N < M
         *     - ^N  : remove a single CPU number from the current set
         */
        if (*cur == '^') {
            cur++;
            neg = true;
        }

        if (!c_isdigit(*cur))
            goto error;

        if (virStrToLong_i(cur, &tmp, 10, &start) < 0)
            goto error;
        if (start < 0)
            goto error;

        cur = tmp;

        virSkipSpaces(&cur);

        if (*cur == ',' || *cur == 0 || *cur == terminator) {
            if (neg) {
                if (virBitmapClearBit(*bitmap, start) < 0)
                    goto error;
            } else {
                if (virBitmapSetBit(*bitmap, start) < 0)
                    goto error;
            }
        } else if (*cur == '-') {
            if (neg)
                goto error;

            cur++;
            virSkipSpaces(&cur);

            if (virStrToLong_i(cur, &tmp, 10, &last) < 0)
                goto error;
            if (last < start)
                goto error;

            cur = tmp;

            for (i = start; i <= last; i++) {
                if (virBitmapSetBit(*bitmap, i) < 0)
                    goto error;
            }

            virSkipSpaces(&cur);
        }

        if (*cur == ',') {
            cur++;
            virSkipSpaces(&cur);
            neg = false;
        } else if (*cur == 0 || *cur == terminator) {
            break;
        } else {
            goto error;
        }
    }

    if (virBitmapIsAllClear(*bitmap))
        goto error;

    return virBitmapCountBits(*bitmap);

 error:
    virReportError(VIR_ERR_INVALID_ARG,
                   _("Failed to parse bitmap '%s'"), str);
    virBitmapFree(*bitmap);
    *bitmap = NULL;
    return -1;
}
Example #17
0
static void
dnsmasqCapsSet(dnsmasqCapsPtr caps,
               dnsmasqCapsFlags flag)
{
    ignore_value(virBitmapSetBit(caps->flags, flag));
}
Example #18
0
/* Align def->disks to def->domain.  Sort the list of def->disks,
 * filling in any missing disks or snapshot state defaults given by
 * the domain, with a fallback to a passed in default.  Convert paths
 * to disk targets for uniformity.  Issue an error and return -1 if
 * any def->disks[n]->name appears more than once or does not map to
 * dom->disks.  If require_match, also ensure that there is no
 * conflicting requests for both internal and external snapshots.  */
int
virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
                            int default_snapshot,
                            bool require_match)
{
    int ret = -1;
    virBitmapPtr map = NULL;
    int i;
    int ndisks;
    bool inuse;

    if (!def->dom) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing domain in snapshot"));
        goto cleanup;
    }

    if (def->ndisks > def->dom->ndisks) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("too many disk snapshot requests for domain"));
        goto cleanup;
    }

    /* Unlikely to have a guest without disks but technically possible.  */
    if (!def->dom->ndisks) {
        ret = 0;
        goto cleanup;
    }

    if (!(map = virBitmapNew(def->dom->ndisks))) {
        virReportOOMError();
        goto cleanup;
    }

    /* Double check requested disks.  */
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];
        int idx = virDomainDiskIndexByName(def->dom, disk->name, false);
        int disk_snapshot;

        if (idx < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("no disk named '%s'"), disk->name);
            goto cleanup;
        }

        if (virBitmapGetBit(map, idx, &inuse) < 0 || inuse) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk '%s' specified twice"),
                           disk->name);
            goto cleanup;
        }
        ignore_value(virBitmapSetBit(map, idx));
        disk->index = idx;

        disk_snapshot = def->dom->disks[idx]->snapshot;
        if (!disk->snapshot) {
            if (disk_snapshot &&
                (!require_match ||
                 disk_snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE))
                disk->snapshot = disk_snapshot;
            else
                disk->snapshot = default_snapshot;
        } else if (require_match &&
                   disk->snapshot != default_snapshot &&
                   !(disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
                     disk_snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)) {
            const char *tmp;

            tmp = virDomainSnapshotLocationTypeToString(default_snapshot);
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk '%s' must use snapshot mode '%s'"),
                           disk->name, tmp);
            goto cleanup;
        }
        if (disk->file &&
            disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("file '%s' for disk '%s' requires "
                             "use of external snapshot mode"),
                           disk->file, disk->name);
            goto cleanup;
        }
        if (STRNEQ(disk->name, def->dom->disks[idx]->dst)) {
            VIR_FREE(disk->name);
            if (!(disk->name = strdup(def->dom->disks[idx]->dst))) {
                virReportOOMError();
                goto cleanup;
            }
        }
    }

    /* Provide defaults for all remaining disks.  */
    ndisks = def->ndisks;
    if (VIR_EXPAND_N(def->disks, def->ndisks,
                     def->dom->ndisks - def->ndisks) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    for (i = 0; i < def->dom->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk;

        ignore_value(virBitmapGetBit(map, i, &inuse));
        if (inuse)
            continue;
        disk = &def->disks[ndisks++];
        if (!(disk->name = strdup(def->dom->disks[i]->dst))) {
            virReportOOMError();
            goto cleanup;
        }
        disk->index = i;
        disk->snapshot = def->dom->disks[i]->snapshot;
        if (!disk->snapshot)
            disk->snapshot = default_snapshot;
    }

    qsort(&def->disks[0], def->ndisks, sizeof(def->disks[0]), disksorter);

    /* Generate any default external file names, but only if the
     * backing file is a regular file.  */
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];

        if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL &&
            !disk->file) {
            const char *original = def->dom->disks[i]->src;
            const char *tmp;
            struct stat sb;

            if (!original) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("cannot generate external snapshot name "
                                 "for disk '%s' without source"),
                               disk->name);
                goto cleanup;
            }
            if (stat(original, &sb) < 0 || !S_ISREG(sb.st_mode)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("source for disk '%s' is not a regular "
                                 "file; refusing to generate external "
                                 "snapshot name"),
                               disk->name);
                goto cleanup;
            }

            tmp = strrchr(original, '.');
            if (!tmp || strchr(tmp, '/')) {
                ignore_value(virAsprintf(&disk->file, "%s.%s",
                                         original, def->name));
            } else {
                if ((tmp - original) > INT_MAX) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("integer overflow"));
                    goto cleanup;
                }
                ignore_value(virAsprintf(&disk->file, "%.*s.%s",
                                         (int) (tmp - original), original,
                                         def->name));
            }
            if (!disk->file) {
                virReportOOMError();
                goto cleanup;
            }
        }
    }

    ret = 0;

cleanup:
    virBitmapFree(map);
    return ret;
}
Example #19
0
int virBitmapParse(const char *str,
                   char sep,
                   virBitmapPtr *bitmap,
                   size_t bitmapSize)
{
    int ret = 0;
    bool neg = false;
    const char *cur;
    char *tmp;
    int i, start, last;

    if (!str)
        return -1;

    cur = str;
    virSkipSpaces(&cur);

    if (*cur == 0)
        return -1;

    *bitmap = virBitmapNew(bitmapSize);
    if (!*bitmap)
        return -1;

    while (*cur != 0 && *cur != sep) {
        /*
         * 3 constructs are allowed:
         *     - N   : a single CPU number
         *     - N-M : a range of CPU numbers with N < M
         *     - ^N  : remove a single CPU number from the current set
         */
        if (*cur == '^') {
            cur++;
            neg = true;
        }

        if (!c_isdigit(*cur))
            goto parse_error;

        if (virStrToLong_i(cur, &tmp, 10, &start) < 0)
            goto parse_error;
        if (start < 0)
            goto parse_error;

        cur = tmp;

        virSkipSpaces(&cur);

        if (*cur == ',' || *cur == 0 || *cur == sep) {
            if (neg) {
                if (virBitmapIsSet(*bitmap, start)) {
                    ignore_value(virBitmapClearBit(*bitmap, start));
                    ret--;
                }
            } else {
                if (!virBitmapIsSet(*bitmap, start)) {
                    ignore_value(virBitmapSetBit(*bitmap, start));
                    ret++;
                }
            }
        } else if (*cur == '-') {
            if (neg)
                goto parse_error;

            cur++;
            virSkipSpaces(&cur);

            if (virStrToLong_i(cur, &tmp, 10, &last) < 0)
                goto parse_error;
            if (last < start)
                goto parse_error;

            cur = tmp;

            for (i = start; i <= last; i++) {
                if (!virBitmapIsSet(*bitmap, i)) {
                    ignore_value(virBitmapSetBit(*bitmap, i));
                    ret++;
                }
            }

            virSkipSpaces(&cur);
        }

        if (*cur == ',') {
            cur++;
            virSkipSpaces(&cur);
            neg = false;
        } else if(*cur == 0 || *cur == sep) {
            break;
        } else {
            goto parse_error;
        }
    }

    return ret;

parse_error:
    virBitmapFree(*bitmap);
    *bitmap = NULL;
    return -1;
}