コード例 #1
0
static int gather_pci_cap(LibHalContext *ctx, const char *udi,
                          union _virNodeDevCapData *d)
{
    char *sysfs_path;

    if (get_str_prop(ctx, udi, "pci.linux.sysfs_path", &sysfs_path) == 0) {
        char *p = strrchr(sysfs_path, '/');
        if (p) {
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.domain);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.bus);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.slot);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.function);
        }

        if (!pciGetPhysicalFunction(sysfs_path, &d->pci_dev.physical_function))
            d->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;

        if (!pciGetVirtualFunctions(sysfs_path, &d->pci_dev.virtual_functions,
            &d->pci_dev.num_virtual_functions) ||
            d->pci_dev.num_virtual_functions > 0)
            d->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;

        VIR_FREE(sysfs_path);
    }

    (void)get_int_prop(ctx, udi, "pci.vendor_id", (int *)&d->pci_dev.vendor);
    if (get_str_prop(ctx, udi, "pci.vendor", &d->pci_dev.vendor_name) != 0)
        (void)get_str_prop(ctx, udi, "info.vendor", &d->pci_dev.vendor_name);
    (void)get_int_prop(ctx, udi, "pci.product_id", (int *)&d->pci_dev.product);
    if (get_str_prop(ctx, udi, "pci.product", &d->pci_dev.product_name) != 0)
        (void)get_str_prop(ctx, udi, "info.product", &d->pci_dev.product_name);

    return 0;
}
コード例 #2
0
ファイル: node_device_hal.c プロジェクト: Archer-sys/libvirt
static int
gather_pci_cap(LibHalContext *ctx, const char *udi,
               virNodeDevCapDataPtr d)
{
    char *sysfs_path;

    if (get_str_prop(ctx, udi, "pci.linux.sysfs_path", &sysfs_path) == 0) {
        char *p = strrchr(sysfs_path, '/');
        if (p) {
            ignore_value(virStrToLong_ui(p+1, &p, 16, &d->pci_dev.domain));
            ignore_value(virStrToLong_ui(p+1, &p, 16, &d->pci_dev.bus));
            ignore_value(virStrToLong_ui(p+1, &p, 16, &d->pci_dev.slot));
            ignore_value(virStrToLong_ui(p+1, &p, 16, &d->pci_dev.function));
        }

        if (nodeDeviceSysfsGetPCIRelatedDevCaps(sysfs_path, d) < 0) {
            VIR_FREE(sysfs_path);
            return -1;
        }
        VIR_FREE(sysfs_path);
    }

    (void)get_int_prop(ctx, udi, "pci.vendor_id", (int *)&d->pci_dev.vendor);
    if (get_str_prop(ctx, udi, "pci.vendor", &d->pci_dev.vendor_name) != 0)
        (void)get_str_prop(ctx, udi, "info.vendor", &d->pci_dev.vendor_name);
    (void)get_int_prop(ctx, udi, "pci.product_id", (int *)&d->pci_dev.product);
    if (get_str_prop(ctx, udi, "pci.product", &d->pci_dev.product_name) != 0)
        (void)get_str_prop(ctx, udi, "info.product", &d->pci_dev.product_name);

    return 0;
}
コード例 #3
0
ファイル: node_device_hal.c プロジェクト: rbu/libvirt
static int gather_pci_cap(LibHalContext *ctx, const char *udi,
                          union _virNodeDevCapData *d)
{
    char *sysfs_path;

    if (get_str_prop(ctx, udi, "pci.linux.sysfs_path", &sysfs_path) == 0) {
        char *p = strrchr(sysfs_path, '/');
        if (p) {
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.domain);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.bus);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.slot);
            (void)virStrToLong_ui(p+1, &p, 16, &d->pci_dev.function);
        }

        get_physical_function(sysfs_path, d);
        get_virtual_functions(sysfs_path, d);

        VIR_FREE(sysfs_path);
    }

    (void)get_int_prop(ctx, udi, "pci.vendor_id", (int *)&d->pci_dev.vendor);
    if (get_str_prop(ctx, udi, "pci.vendor", &d->pci_dev.vendor_name) != 0)
        (void)get_str_prop(ctx, udi, "info.vendor", &d->pci_dev.vendor_name);
    (void)get_int_prop(ctx, udi, "pci.product_id", (int *)&d->pci_dev.product);
    if (get_str_prop(ctx, udi, "pci.product", &d->pci_dev.product_name) != 0)
        (void)get_str_prop(ctx, udi, "info.product", &d->pci_dev.product_name);

    return 0;
}
コード例 #4
0
ファイル: virnuma.c プロジェクト: AGSaidi/hacked-libvirt
/**
 * virNumaGetHugePageInfo:
 * @node: NUMA node id
 * @page_size: which huge page are we interested in
 * @page_avail: total number of huge pages in the pool
 * @page_free: the number of free huge pages in the pool
 *
 * For given NUMA node and huge page size fetch information on
 * total number of huge pages in the pool (both free and taken)
 * and count for free huge pages in the pool.
 *
 * If you're interested in just one bit, pass NULL to the other one.
 *
 * As a special case, if @node == -1, overall info is fetched
 * from the system.
 *
 * Returns 0 on success, -1 otherwise (with error reported).
 */
static int
virNumaGetHugePageInfo(int node,
                       unsigned int page_size,
                       unsigned int *page_avail,
                       unsigned int *page_free)
{
    int ret = -1;
    char *path = NULL;
    char *buf = NULL;
    char *end;

    if (page_avail) {
        if (virNumaGetHugePageInfoPath(&path, node,
                                       page_size, "nr_hugepages") < 0)
            goto cleanup;

        if (virFileReadAll(path, 1024, &buf) < 0)
            goto cleanup;

        if (virStrToLong_ui(buf, &end, 10, page_avail) < 0 ||
                *end != '\n') {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unable to parse: %s"),
                           buf);
            goto cleanup;
        }
        VIR_FREE(buf);
        VIR_FREE(path);
    }

    if (page_free) {
        if (virNumaGetHugePageInfoPath(&path, node,
                                       page_size, "free_hugepages") < 0)
            goto cleanup;

        if (virFileReadAll(path, 1024, &buf) < 0)
            goto cleanup;

        if (virStrToLong_ui(buf, &end, 10, page_free) < 0 ||
                *end != '\n') {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unable to parse: %s"),
                           buf);
            goto cleanup;
        }
    }

    ret = 0;
cleanup:
    VIR_FREE(buf);
    VIR_FREE(path);
    return ret;
}
コード例 #5
0
ファイル: json.c プロジェクト: foomango/libvirt
int virJSONValueGetNumberUint(virJSONValuePtr number, unsigned int *value)
{
    if (number->type != VIR_JSON_TYPE_NUMBER)
        return -1;

    return virStrToLong_ui(number->data.number, NULL, 10, value);
}
コード例 #6
0
ファイル: hostusb.c プロジェクト: emaste/libvirt
static int usbSysReadFile(const char *f_name, const char *d_name,
                          int base, unsigned int *value)
{
    int ret = -1, tmp;
    char *buf = NULL;
    char *filename = NULL;
    char *ignore = NULL;

    tmp = virAsprintf(&filename, USB_SYSFS "/devices/%s/%s", d_name, f_name);
    if (tmp < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (virFileReadAll(filename, 1024, &buf) < 0)
        goto cleanup;

    if (virStrToLong_ui(buf, &ignore, base, value) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not parse usb file %s"), filename);
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FREE(filename);
    VIR_FREE(buf);
    return ret;
}
コード例 #7
0
static uint32_t
virNetDevVPortProfileGetLldpadPid(void)
{
    int fd;
    uint32_t pid = 0;

    fd = open(LLDPAD_PID_FILE, O_RDONLY);
    if (fd >= 0) {
        char buffer[10];

        if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) {
            unsigned int res;
            char *endptr;

            if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0
                && (*endptr == '\0' || c_isspace(*endptr))
                && res != 0) {
                pid = res;
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("error parsing pid of lldpad"));
            }
        }
    } else {
        virReportSystemError(errno,
                             _("Error opening file %s"), LLDPAD_PID_FILE);
    }

    VIR_FORCE_CLOSE(fd);

    return pid;
}
コード例 #8
0
int
virInterfaceLinkParseXML(xmlNodePtr node,
                         virInterfaceLinkPtr lnk)
{
    int ret = -1;
    char *stateStr, *speedStr;
    int state;

    stateStr = virXMLPropString(node, "state");
    speedStr = virXMLPropString(node, "speed");

    if (stateStr) {
        if ((state = virInterfaceStateTypeFromString(stateStr)) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("unknown link state: %s"),
                           stateStr);
            goto cleanup;
        }
        lnk->state = state;
    }

    if (speedStr &&
        virStrToLong_ui(speedStr, NULL, 10, &lnk->speed) < 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("Unable to parse link speed: %s"),
                       speedStr);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    VIR_FREE(stateStr);
    VIR_FREE(speedStr);
    return ret;
}
コード例 #9
0
ファイル: virnetdevmacvlan.c プロジェクト: Archer-sys/libvirt
/**
 * virNetDevMacVLanReleaseName:
 *
 *  @name: already-known name of device
 *
 *  Extract the device type and id from a macvtap/macvlan device name
 *  and mark the appropriate position as in-use in the appropriate
 *  bitmap.
 *
 *  returns 0 on success, -1 on failure
 */
int
virNetDevMacVLanReleaseName(const char *name)
{
    unsigned int id;
    unsigned int flags = 0;
    const char *idstr = NULL;

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

    if (STRPREFIX(name, MACVTAP_NAME_PREFIX)) {
        idstr = name + strlen(MACVTAP_NAME_PREFIX);
        flags |= VIR_NETDEV_MACVLAN_CREATE_WITH_TAP;
    } else if (STRPREFIX(name, MACVLAN_NAME_PREFIX)) {
        idstr = name + strlen(MACVLAN_NAME_PREFIX);
    } else {
        return 0;
    }

    if (virStrToLong_ui(idstr, NULL, 10, &id) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("couldn't get id value from macvtap device name %s"),
                       name);
        return -1;
    }
    return virNetDevMacVLanReleaseID(id, flags);
}
コード例 #10
0
static int
bhyveParsePCISlot(const char *slotdef,
                  unsigned *pcislot,
                  unsigned *bus,
                  unsigned *function)
{
    /* slot[:function] | bus:slot:function */
    const char *curr = NULL;
    const char *next = NULL;
    unsigned values[3];
    size_t i;

    curr = slotdef;
    for (i = 0; i < 3; i++) {
       char *val = NULL;

       next = strchr(curr, ':');

       if (VIR_STRNDUP(val, curr, next? next - curr : -1) < 0)
           goto error;

       if (virStrToLong_ui(val, NULL, 10, &values[i]) < 0)
           goto error;

       VIR_FREE(val);

       if (!next)
           break;

       curr = next +1;
    }

    *bus = 0;
    *pcislot = 0;
    *function = 0;

    switch (i + 1) {
    case 2:
        /* pcislot[:function] */
        *function = values[1];
    case 1:
        *pcislot = values[0];
        break;
    case 3:
        /* bus:pcislot:function */
        *bus = values[0];
        *pcislot = values[1];
        *function = values[2];
        break;
    }

    return 0;
 error:
    return -1;
}
コード例 #11
0
ファイル: virscsi.c プロジェクト: MountainWei/libvirt
static int
virSCSIDeviceGetAdapterId(const char *adapter,
                          unsigned int *adapter_id)
{
    if (STRPREFIX(adapter, "scsi_host") &&
        virStrToLong_ui(adapter + strlen("scsi_host"),
                        NULL, 0, adapter_id) == 0)
        return 0;
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Cannot parse adapter '%s'"), adapter);
    return -1;
}
コード例 #12
0
ファイル: testutils.c プロジェクト: yangfeng724/libvirt
static unsigned int
virTestGetFlag(const char *name)
{
    char *flagStr;
    unsigned int flag;

    if ((flagStr = getenv(name)) == NULL)
        return 0;

    if (virStrToLong_ui(flagStr, NULL, 10, &flag) < 0)
        return 0;

    return flag;
}
コード例 #13
0
static int logStrToLong_ui(char const *s,
                           char **end_ptr,
                           int base,
                           unsigned int *result)
{
    int ret = 0;

    ret = virStrToLong_ui(s, end_ptr, base, result);
    if (ret != 0) {
        VIR_ERROR(_("Failed to convert '%s' to unsigned int"), s);
    } else {
        VIR_DEBUG("Converted '%s' to unsigned int %u", s, *result);
    }

    return ret;
}
コード例 #14
0
ファイル: lxc_native.c プロジェクト: tdaajames/libvirt
static int
lxcSetBlkioTune(virDomainDefPtr def, virConfPtr properties)
{
    virConfValuePtr value;

    if ((value = virConfGetValue(properties, "lxc.cgroup.blkio.weight")) &&
            value->str && virStrToLong_ui(value->str, NULL, 10,
                                          &def->blkio.weight) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse integer: '%s'"), value->str);
        return -1;
    }

    if (virConfWalk(properties, lxcBlkioDeviceWalkCallback, def) < 0)
        return -1;

    return 0;
}
コード例 #15
0
ファイル: lxc_native.c プロジェクト: libvirt/libvirt
static int
lxcSetBlkioTune(virDomainDefPtr def, virConfPtr properties)
{
    VIR_AUTOFREE(char *) value = NULL;

    if (virConfGetValueString(properties, "lxc.cgroup.blkio.weight",
                              &value) > 0) {
        if (virStrToLong_ui(value, NULL, 10, &def->blkio.weight) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse integer: '%s'"), value);
            return -1;
        }
    }

    if (virConfWalk(properties, lxcBlkioDeviceWalkCallback, def) < 0)
        return -1;

    return 0;
}
コード例 #16
0
ファイル: virrandom.c プロジェクト: FrankYu/libvirt
static int
virRandomOnceInit(void)
{
    unsigned int seed = time(NULL) ^ getpid();

#if 0
    /* Normally we want a decent seed.  But if reproducible debugging
     * of a fixed pseudo-random sequence is ever required, uncomment
     * this block to let an environment variable force the seed.  */
    const char *debug = virGetEnvBlockSUID("VIR_DEBUG_RANDOM_SEED");

    if (debug && virStrToLong_ui(debug, NULL, 0, &seed) < 0)
        return -1;
#endif

    if (initstate_r(seed,
                    randomState,
                    sizeof(randomState),
                    &randomData) < 0)
        return -1;

    return 0;
}
コード例 #17
0
ファイル: lxc_native.c プロジェクト: libvirt/libvirt
static int
lxcNetworkParseDataIPs(const char *name,
                       virConfValuePtr value,
                       lxcNetworkParseData *parseData)
{
    int family = AF_INET;
    char **ipparts = NULL;
    virNetDevIPAddrPtr ip = NULL;

    if (VIR_ALLOC(ip) < 0)
        return -1;

    if (STREQ(name, "ipv6"))
        family = AF_INET6;

    ipparts = virStringSplit(value->str, "/", 2);
    if (virStringListLength((const char * const *)ipparts) != 2 ||
        virSocketAddrParse(&ip->address, ipparts[0], family) < 0 ||
        virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) {

        virReportError(VIR_ERR_INVALID_ARG,
                       _("Invalid CIDR address: '%s'"), value->str);

        virStringListFree(ipparts);
        VIR_FREE(ip);
        return -1;
    }

    virStringListFree(ipparts);

    if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) {
        VIR_FREE(ip);
        return -1;
    }

    return 0;
}
コード例 #18
0
ファイル: lxc_native.c プロジェクト: tdaajames/libvirt
static int
lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
{
    lxcNetworkParseData *parseData = data;
    int status;

    if (STREQ(name, "lxc.network.type")) {
        /* Store the previous NIC */
        status = lxcAddNetworkDefinition(parseData);

        if (status < 0)
            return -1;
        else if (status > 0)
            parseData->networks++;
        else if (parseData->type != NULL && STREQ(parseData->type, "none"))
            parseData->privnet = false;

        /* Start a new network interface config */
        parseData->type = NULL;
        parseData->link = NULL;
        parseData->mac = NULL;
        parseData->flag = NULL;
        parseData->macvlanmode = NULL;
        parseData->vlanid = NULL;
        parseData->name = NULL;

        parseData->ips = NULL;
        parseData->nips = 0;

        /* Keep the new value */
        parseData->type = value->str;
    }
    else if (STREQ(name, "lxc.network.link"))
        parseData->link = value->str;
    else if (STREQ(name, "lxc.network.hwaddr"))
        parseData->mac = value->str;
    else if (STREQ(name, "lxc.network.flags"))
        parseData->flag = value->str;
    else if (STREQ(name, "lxc.network.macvlan.mode"))
        parseData->macvlanmode = value->str;
    else if (STREQ(name, "lxc.network.vlan.id"))
        parseData->vlanid = value->str;
    else if (STREQ(name, "lxc.network.name"))
        parseData->name = value->str;
    else if (STREQ(name, "lxc.network.ipv4") ||
             STREQ(name, "lxc.network.ipv6")) {
        int family = AF_INET;
        char **ipparts = NULL;
        virDomainNetIpDefPtr ip = NULL;

        if (VIR_ALLOC(ip) < 0)
            return -1;

        if (STREQ(name, "lxc.network.ipv6"))
            family = AF_INET6;

        ipparts = virStringSplit(value->str, "/", 2);
        if (virStringListLength((const char * const *)ipparts) != 2 ||
            virSocketAddrParse(&ip->address, ipparts[0], family) < 0 ||
            virStrToLong_ui(ipparts[1], NULL, 10, &ip->prefix) < 0) {

            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid CIDR address: '%s'"), value->str);

            virStringFreeList(ipparts);
            VIR_FREE(ip);
            return -1;
        }

        virStringFreeList(ipparts);

        if (VIR_APPEND_ELEMENT(parseData->ips, parseData->nips, ip) < 0) {
            VIR_FREE(ip);
            return -1;
        }
    } else if (STREQ(name, "lxc.network.ipv4.gateway")) {
        parseData->gateway_ipv4 = value->str;
    } else if (STREQ(name, "lxc.network.ipv6.gateway")) {
        parseData->gateway_ipv6 = value->str;
    } else if (STRPREFIX(name, "lxc.network")) {
        VIR_WARN("Unhandled network property: %s = %s",
                 name,
                 value->str);
    }

    return 0;
}
コード例 #19
0
ファイル: virnuma.c プロジェクト: AGSaidi/hacked-libvirt
/**
 * virNumaGetPages:
 * @node: NUMA node id
 * @pages_size: list of pages supported on @node
 * @pages_avail: list of the pool sizes on @node
 * @pages_free: list of free pages on @node
 * @npages: the lists size
 *
 * For given NUMA node fetch info on pages. The size of pages
 * (e.g.  4K, 2M, 1G) is stored into @pages_size, the size of the
 * pool is then stored into @pages_avail and the number of free
 * pages in the pool is stored into @pages_free.
 *
 * If you're interested only in some lists, pass NULL to the
 * other ones.
 *
 * As a special case, if @node == -1, overall info is fetched
 * from the system.
 *
 * Returns 0 on success, -1 otherwise.
 */
int
virNumaGetPages(int node,
                unsigned int **pages_size,
                unsigned int **pages_avail,
                unsigned int **pages_free,
                size_t *npages)
{
    int ret = -1;
    char *path = NULL;
    DIR *dir = NULL;
    int direrr = 0;
    struct dirent *entry;
    unsigned int *tmp_size = NULL, *tmp_avail = NULL, *tmp_free = NULL;
    unsigned int ntmp = 0;
    size_t i;
    bool exchange;
    long system_page_size;
    unsigned long long huge_page_sum = 0;

    /* sysconf() returns page size in bytes,
     * but we are storing the page size in kibibytes. */
    system_page_size = virGetSystemPageSizeKB();

    /* Query huge pages at first.
     * On Linux systems, the huge pages pool cuts off the available memory and
     * is always shown as used memory. Here, however, we want to report
     * slightly different information. So we take the total memory on a node
     * and subtract memory taken by the huge pages. */
    if (virNumaGetHugePageInfoPath(&path, node, 0, NULL) < 0)
        goto cleanup;

    if (!(dir = opendir(path))) {
        /* It's okay if the @path doesn't exist. Maybe we are running on
         * system without huge pages support where the path may not exist. */
        if (errno != ENOENT) {
            virReportSystemError(errno,
                                 _("unable to open path: %s"),
                                 path);
            goto cleanup;
        }
    }

    while (dir && (direrr = virDirRead(dir, &entry, path)) > 0) {
        const char *page_name = entry->d_name;
        unsigned int page_size, page_avail = 0, page_free = 0;
        char *end;

        /* Just to give you a hint, we're dealing with this:
         * hugepages-2048kB/  or   hugepages-1048576kB/ */
        if (!STRPREFIX(entry->d_name, HUGEPAGES_PREFIX))
            continue;

        page_name += strlen(HUGEPAGES_PREFIX);

        if (virStrToLong_ui(page_name, &end, 10, &page_size) < 0 ||
                STRCASENEQ(end, "kB")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unable to parse %s"),
                           entry->d_name);
            goto cleanup;
        }

        if (virNumaGetHugePageInfo(node, page_size,
                                   &page_avail, &page_free) < 0)
            goto cleanup;

        if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 ||
                VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 ||
                VIR_REALLOC_N(tmp_free, ntmp + 1) < 0)
            goto cleanup;

        tmp_size[ntmp] = page_size;
        tmp_avail[ntmp] = page_avail;
        tmp_free[ntmp] = page_free;
        ntmp++;

        /* page_size is in kibibytes while we want huge_page_sum
         * in just bytes. */
        huge_page_sum += 1024 * page_size * page_avail;
    }

    if (direrr < 0)
        goto cleanup;

    /* Now append the ordinary system pages */
    if (VIR_REALLOC_N(tmp_size, ntmp + 1) < 0 ||
            VIR_REALLOC_N(tmp_avail, ntmp + 1) < 0 ||
            VIR_REALLOC_N(tmp_free, ntmp + 1) < 0)
        goto cleanup;

    if (virNumaGetPageInfo(node, system_page_size, huge_page_sum,
                           &tmp_avail[ntmp], &tmp_free[ntmp]) < 0)
        goto cleanup;
    tmp_size[ntmp] = system_page_size;
    ntmp++;

    /* Just to produce nice output, sort the arrays by increasing page size */
    do {
        exchange = false;
        for (i = 0; i < ntmp -1; i++) {
            if (tmp_size[i] > tmp_size[i + 1]) {
                exchange = true;
                SWAP(tmp_size[i], tmp_size[i + 1]);
                SWAP(tmp_avail[i], tmp_avail[i + 1]);
                SWAP(tmp_free[i], tmp_free[i + 1]);
            }
        }
    } while (exchange);

    if (pages_size) {
        *pages_size = tmp_size;
        tmp_size = NULL;
    }
    if (pages_avail) {
        *pages_avail = tmp_avail;
        tmp_avail = NULL;
    }
    if (pages_free) {
        *pages_free = tmp_free;
        tmp_free = NULL;
    }
    *npages = ntmp;
    ret = 0;
cleanup:
    VIR_FREE(tmp_free);
    VIR_FREE(tmp_avail);
    VIR_FREE(tmp_size);
    if (dir)
        closedir(dir);
    VIR_FREE(path);
    return ret;
}
コード例 #20
0
ファイル: hostusb.c プロジェクト: emaste/libvirt
static usbDeviceList *
usbDeviceSearch(unsigned int vendor,
                unsigned int product,
                unsigned int bus,
                unsigned int devno,
                const char *vroot,
                unsigned int flags)
{
    DIR *dir = NULL;
    bool found = false;
    char *ignore = NULL;
    struct dirent *de;
    usbDeviceList *list = NULL, *ret = NULL;
    usbDevice *usb;

    if (!(list = usbDeviceListNew()))
        goto cleanup;

    dir = opendir(USB_SYSFS "/devices");
    if (!dir) {
        virReportSystemError(errno,
                             _("Could not open directory %s"),
                             USB_SYSFS "/devices");
        goto cleanup;
    }

    while ((de = readdir(dir))) {
        unsigned int found_prod, found_vend, found_bus, found_devno;
        char *tmpstr = de->d_name;

        if (de->d_name[0] == '.' || strchr(de->d_name, ':'))
            continue;

        if (usbSysReadFile("idVendor", de->d_name,
                           16, &found_vend) < 0)
            goto cleanup;

        if (usbSysReadFile("idProduct", de->d_name,
                           16, &found_prod) < 0)
            goto cleanup;

        if (STRPREFIX(de->d_name, "usb"))
            tmpstr += 3;

        if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to parse dir name '%s'"),
                           de->d_name);
            goto cleanup;
        }

        if (usbSysReadFile("devnum", de->d_name,
                           10, &found_devno) < 0)
            goto cleanup;

        if ((flags & USB_DEVICE_FIND_BY_VENDOR) &&
            (found_prod != product || found_vend != vendor))
            continue;

        if (flags & USB_DEVICE_FIND_BY_BUS) {
            if (found_bus != bus || found_devno != devno)
                continue;
            found = true;
        }

        usb = usbGetDevice(found_bus, found_devno, vroot);
        if (!usb)
            goto cleanup;

        if (usbDeviceListAdd(list, usb) < 0) {
            usbFreeDevice(usb);
            goto cleanup;
        }

        if (found)
            break;
    }
    ret = list;

cleanup:
    if (dir) {
        int saved_errno = errno;
        closedir(dir);
        errno = saved_errno;
    }

    if (!ret)
        usbDeviceListFree(list);
    return ret;
}
コード例 #21
0
ファイル: nodeinfo.c プロジェクト: amery/libvirt-vserver
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                             virNodeInfoPtr nodeinfo)
{
    char line[1024];
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    unsigned int cpu;
    unsigned long cur_threads;
    int socket;
    unsigned long long socket_mask = 0;
    unsigned int remaining;
    int online;

    nodeinfo->cpus = 0;
    nodeinfo->mhz = 0;
    nodeinfo->cores = 1;

    nodeinfo->nodes = 1;
# if HAVE_NUMACTL
    if (numa_available() >= 0)
        nodeinfo->nodes = numa_max_node() + 1;
# endif

    /* NB: It is impossible to fill our nodes, since cpuinfo
     * has no knowledge of NUMA nodes */

    /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
        char *buf = line;
        if (STRPREFIX(buf, "processor")) { /* aka a single logical CPU */
            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':') {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo processor"));
                return -1;
            }
            nodeinfo->cpus++;
        } else if (STRPREFIX(buf, "cpu MHz")) {
            char *p;
            unsigned int ui;
            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo cpu MHz"));
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        } else if (STRPREFIX(buf, "cpu cores")) { /* aka cores */
            char *p;
            unsigned int id;
            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "parsing cpuinfo cpu cores %c", *buf);
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &id) == 0
                && (*p == '\0' || c_isspace(*p))
                && id > nodeinfo->cores)
                nodeinfo->cores = id;
        }
    }

    if (!nodeinfo->cpus) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no cpus found"));
        return -1;
    }

    /* OK, we've parsed what we can out of /proc/cpuinfo.  Get the socket
     * and thread information from /sys
     */
    remaining = nodeinfo->cpus;
    cpudir = opendir(CPU_SYS_PATH);
    if (cpudir == NULL) {
        virReportSystemError(errno, _("cannot opendir %s"), CPU_SYS_PATH);
        return -1;
    }
    while ((errno = 0), remaining && (cpudirent = readdir(cpudir))) {
        if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
            continue;

        online = cpu_online(cpu);
        if (online < 0) {
            closedir(cpudir);
            return -1;
        }
        if (!online)
            continue;
        remaining--;

        socket = parse_socket(cpu);
        if (socket < 0) {
            closedir(cpudir);
            return -1;
        }
        if (!(socket_mask & (1 << socket))) {
            socket_mask |= (1 << socket);
            nodeinfo->sockets++;
        }

        cur_threads = count_thread_siblings(cpu);
        if (cur_threads == 0) {
            closedir(cpudir);
            return -1;
        }
        if (cur_threads > nodeinfo->threads)
            nodeinfo->threads = cur_threads;
    }
    if (errno) {
        virReportSystemError(errno,
                             _("problem reading %s"), CPU_SYS_PATH);
        closedir(cpudir);
        return -1;
    }

    closedir(cpudir);

    /* there should always be at least one socket and one thread */
    if (nodeinfo->sockets == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no sockets found"));
        return -1;
    }
    if (nodeinfo->threads == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no threads found"));
        return -1;
    }

    return 0;
}
コード例 #22
0
ファイル: security_dac.c プロジェクト: xushiwei/libvirt
static
int parseIds(const char *label, uid_t *uidPtr, gid_t *gidPtr)
{
    int rc = -1;
    unsigned int theuid;
    unsigned int thegid;
    char *tmp_label = NULL;
    char *sep = NULL;
    char *owner = NULL;
    char *group = NULL;

    tmp_label = strdup(label);
    if (tmp_label == NULL) {
        virReportOOMError();
        goto cleanup;
    }

    /* Split label */
    sep = strchr(tmp_label, ':');
    if (sep == NULL) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("Missing separator ':' in DAC label \"%s\""),
                       label);
        goto cleanup;
    }
    *sep = '\0';
    owner = tmp_label;
    group = sep + 1;

    /* Parse owner */
    if (*owner == '+') {
        if (virStrToLong_ui(++owner, NULL, 10, &theuid) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid uid \"%s\" in DAC label \"%s\""),
                           owner, label);
            goto cleanup;
        }
    } else {
        if (virGetUserID(owner, &theuid) < 0 &&
            virStrToLong_ui(owner, NULL, 10, &theuid) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid owner \"%s\" in DAC label \"%s\""),
                           owner, label);
            goto cleanup;
        }
    }

    /* Parse group */
    if (*group == '+') {
        if (virStrToLong_ui(++group, NULL, 10, &thegid) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid gid \"%s\" in DAC label \"%s\""),
                           group, label);
            goto cleanup;
        }
    } else {
        if (virGetGroupID(group, &thegid) < 0 &&
            virStrToLong_ui(group, NULL, 10, &thegid) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid group \"%s\" in DAC label \"%s\""),
                           group, label);
            goto cleanup;
        }
    }

    if (uidPtr)
        *uidPtr = theuid;
    if (gidPtr)
        *gidPtr = thegid;

    rc = 0;

cleanup:
    VIR_FREE(tmp_label);

    return rc;
}
コード例 #23
0
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                             const char *sysfs_cpudir,
                             virNodeInfoPtr nodeinfo)
{
    char line[1024];
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    unsigned int cpu;
    unsigned long core, sock, cur_threads;
    cpu_set_t core_mask;
    cpu_set_t socket_mask;
    int online;

    nodeinfo->cpus = 0;
    nodeinfo->mhz = 0;
    nodeinfo->cores = 0;

    nodeinfo->nodes = 1;
# if HAVE_NUMACTL
    if (numa_available() >= 0)
        nodeinfo->nodes = numa_max_node() + 1;
# endif

    if (!virStrcpyStatic(sysfs_path, sysfs_cpudir)) {
        virReportSystemError(errno, _("cannot copy %s"), sysfs_cpudir);
        return -1;
    }
    /* NB: It is impossible to fill our nodes, since cpuinfo
     * has no knowledge of NUMA nodes */

    /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
# if defined(__x86_64__) || \
    defined(__amd64__)  || \
    defined(__i386__)
        char *buf = line;
        if (STRPREFIX(buf, "cpu MHz")) {
            char *p;
            unsigned int ui;
            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo cpu MHz"));
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        }
# elif defined(__powerpc__) || \
      defined(__powerpc64__)
        char *buf = line;
        if (STRPREFIX(buf, "clock")) {
            char *p;
            unsigned int ui;
            buf += 5;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo cpu MHz"));
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
            /* No other interesting infos are available in /proc/cpuinfo.
             * However, there is a line identifying processor's version,
             * identification and machine, but we don't want it to be caught
             * and parsed in next iteration, because it is not in expected
             * format and thus lead to error. */
        }
# else
#  warning Parser for /proc/cpuinfo needs to be adapted for your architecture
# endif
    }

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the core, socket
     * thread and topology information from /sys
     */
    cpudir = opendir(sysfs_cpudir);
    if (cpudir == NULL) {
        virReportSystemError(errno, _("cannot opendir %s"), sysfs_cpudir);
        return -1;
    }

    CPU_ZERO(&core_mask);
    CPU_ZERO(&socket_mask);

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

        online = cpu_online(cpu);
        if (online < 0) {
            closedir(cpudir);
            return -1;
        }
        if (!online)
            continue;
        nodeinfo->cpus++;

        /* Parse core */
        core = parse_core(cpu);
        if (!CPU_ISSET(core, &core_mask)) {
            CPU_SET(core, &core_mask);
            nodeinfo->cores++;
        }

        /* Parse socket */
        sock = parse_socket(cpu);
        if (!CPU_ISSET(sock, &socket_mask)) {
            CPU_SET(sock, &socket_mask);
            nodeinfo->sockets++;
        }

        cur_threads = count_thread_siblings(cpu);
        if (cur_threads == 0) {
            closedir(cpudir);
            return -1;
        }
        if (cur_threads > nodeinfo->threads)
            nodeinfo->threads = cur_threads;
    }
    if (errno) {
        virReportSystemError(errno,
                             _("problem reading %s"), sysfs_path);
        closedir(cpudir);
        return -1;
    }

    closedir(cpudir);

    /* there should always be at least one cpu, socket and one thread */
    if (nodeinfo->cpus == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no CPUs found"));
        return -1;
    }
    if (nodeinfo->sockets == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no sockets found"));
        return -1;
    }
    if (nodeinfo->threads == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no threads found"));
        return -1;
    }

    /* nodeinfo->sockets is supposed to be a number of sockets per NUMA node,
     * however if NUMA nodes are not composed of whole sockets, we just lie
     * about the number of NUMA nodes and force apps to check capabilities XML
     * for the actual NUMA topology.
     */
    if (nodeinfo->sockets % nodeinfo->nodes == 0)
        nodeinfo->sockets /= nodeinfo->nodes;
    else
        nodeinfo->nodes = 1;

    return 0;
}
コード例 #24
0
ファイル: nodeinfo.c プロジェクト: heidsoft/libvirt
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                             const char *sysfs_dir,
                             virNodeInfoPtr nodeinfo)
{
    char line[1024];
    DIR *nodedir = NULL;
    struct dirent *nodedirent = NULL;
    int cpus, cores, socks, threads, offline = 0;
    unsigned int node;
    int ret = -1;
    char *sysfs_nodedir = NULL;
    char *sysfs_cpudir = NULL;

    /* Start with parsing CPU clock speed from /proc/cpuinfo */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
# if defined(__x86_64__) || \
    defined(__amd64__)  || \
    defined(__i386__)
        char *buf = line;
        if (STRPREFIX(buf, "cpu MHz")) {
            char *p;
            unsigned int ui;

            buf += 7;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("parsing cpu MHz from cpuinfo"));
                goto cleanup;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                /* Accept trailing fractional part.  */
                (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        }

# elif defined(__powerpc__) || \
      defined(__powerpc64__)
        char *buf = line;
        if (STRPREFIX(buf, "clock")) {
            char *p;
            unsigned int ui;

            buf += 5;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("parsing cpu MHz from cpuinfo"));
                goto cleanup;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                /* Accept trailing fractional part.  */
                (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
            /* No other interesting infos are available in /proc/cpuinfo.
             * However, there is a line identifying processor's version,
             * identification and machine, but we don't want it to be caught
             * and parsed in next iteration, because it is not in expected
             * format and thus lead to error. */
        }
# elif defined(__arm__)
        char *buf = line;
        if (STRPREFIX(buf, "BogoMIPS")) {
            char *p;
            unsigned int ui;

            buf += 8;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("parsing cpu MHz from cpuinfo"));
                goto cleanup;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        }
# elif defined(__s390__) || \
      defined(__s390x__)
        /* s390x has no realistic value for CPU speed,
         * assign a value of zero to signify this */
        nodeinfo->mhz = 0;
# else
#  warning Parser for /proc/cpuinfo needs to be adapted for your architecture
# endif
    }

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
     * core, node, socket, thread and topology information from /sys
     */
    if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_dir) < 0)
        goto cleanup;

    if (!(nodedir = opendir(sysfs_nodedir))) {
        /* the host isn't probably running a NUMA architecture */
        goto fallback;
    }

    errno = 0;
    while ((nodedirent = readdir(nodedir))) {
        if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
            continue;

        nodeinfo->nodes++;

        if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
                        sysfs_dir, nodedirent->d_name) < 0)
            goto cleanup;

        if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores,
                                     &threads, &offline)) < 0)
            goto cleanup;

        VIR_FREE(sysfs_cpudir);

        nodeinfo->cpus += cpus;

        if (socks > nodeinfo->sockets)
            nodeinfo->sockets = socks;

        if (cores > nodeinfo->cores)
            nodeinfo->cores = cores;

        if (threads > nodeinfo->threads)
            nodeinfo->threads = threads;

        errno = 0;
    }

    if (errno) {
        virReportSystemError(errno, _("problem reading %s"), sysfs_nodedir);
        goto cleanup;
    }

    if (nodeinfo->cpus && nodeinfo->nodes)
        goto done;

fallback:
    VIR_FREE(sysfs_cpudir);

    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_dir) < 0)
        goto cleanup;

    if ((cpus = virNodeParseNode(sysfs_cpudir, &socks, &cores,
                                 &threads, &offline)) < 0)
        goto cleanup;

    nodeinfo->nodes = 1;
    nodeinfo->cpus = cpus;
    nodeinfo->sockets = socks;
    nodeinfo->cores = cores;
    nodeinfo->threads = threads;

done:
    /* There should always be at least one cpu, socket, node, and thread. */
    if (nodeinfo->cpus == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
        goto cleanup;
    }

    if (nodeinfo->sockets == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
        goto cleanup;
    }

    if (nodeinfo->threads == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
        goto cleanup;
    }

    /* Now check if the topology makes sense. There are machines that don't
     * expose their real number of nodes or for example the AMD Bulldozer
     * architecture that exposes their Clustered integer core modules as both
     * threads and cores. This approach throws off our detection. Unfortunately
     * the nodeinfo structure isn't designed to carry the full topology so
     * we're going to lie about the detected topology to notify the user
     * to check the host capabilities for the actual topology. */
    if ((nodeinfo->nodes *
         nodeinfo->sockets *
         nodeinfo->cores *
         nodeinfo->threads) != (nodeinfo->cpus + offline)) {
        nodeinfo->nodes = 1;
        nodeinfo->sockets = 1;
        nodeinfo->cores = nodeinfo->cpus + offline;
        nodeinfo->threads = 1;
    }

    ret = 0;

cleanup:
    /* don't shadow a more serious error */
    if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
        virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
        ret = -1;
    }

    VIR_FREE(sysfs_nodedir);
    VIR_FREE(sysfs_cpudir);
    return ret;
}
コード例 #25
0
ファイル: device_conf.c プロジェクト: ramielrowe/libvirt
int
virDevicePCIAddressParseXML(xmlNodePtr node,
                            virDevicePCIAddressPtr addr)
{
    char *domain, *slot, *bus, *function, *multi;
    int ret = -1;

    memset(addr, 0, sizeof(*addr));

    domain   = virXMLPropString(node, "domain");
    bus      = virXMLPropString(node, "bus");
    slot     = virXMLPropString(node, "slot");
    function = virXMLPropString(node, "function");
    multi    = virXMLPropString(node, "multifunction");

    if (domain &&
        virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot parse <address> 'domain' attribute"));
        goto cleanup;
    }

    if (bus &&
        virStrToLong_ui(bus, NULL, 0, &addr->bus) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot parse <address> 'bus' attribute"));
        goto cleanup;
    }

    if (slot &&
        virStrToLong_ui(slot, NULL, 0, &addr->slot) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot parse <address> 'slot' attribute"));
        goto cleanup;
    }

    if (function &&
        virStrToLong_ui(function, NULL, 0, &addr->function) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Cannot parse <address> 'function' attribute"));
        goto cleanup;
    }

    if (multi &&
        ((addr->multi = virDeviceAddressPciMultiTypeFromString(multi)) <= 0)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Unknown value '%s' for <address> 'multifunction' attribute"),
                       multi);
        goto cleanup;

    }
    if (!virDevicePCIAddressIsValid(addr)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Insufficient specification for PCI address"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(domain);
    VIR_FREE(bus);
    VIR_FREE(slot);
    VIR_FREE(function);
    VIR_FREE(multi);
    return ret;
}
コード例 #26
0
/* XXX: This function can be a lot more exhaustive, there are certainly
 *      other scenarios where we can ruin host network connectivity.
 * XXX: Using a proper library is preferred over parsing /proc
 */
int networkCheckRouteCollision(virNetworkDefPtr def)
{
    int ret = 0, len;
    char *cur, *buf = NULL;
    /* allow for up to 100000 routes (each line is 128 bytes) */
    enum {MAX_ROUTE_SIZE = 128*100000};

    /* Read whole routing table into memory */
    if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
        goto out;

    /* Dropping the last character shouldn't hurt */
    if (len > 0)
        buf[len-1] = '\0';

    VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);

    if (!STRPREFIX(buf, "Iface"))
        goto out;

    /* First line is just headings, skip it */
    cur = strchr(buf, '\n');
    if (cur)
        cur++;

    while (cur) {
        char iface[17], dest[128], mask[128];
        unsigned int addr_val, mask_val;
        virNetworkIpDefPtr ipdef;
        int num;
        size_t i;

        /* NUL-terminate the line, so sscanf doesn't go beyond a newline.  */
        char *nl = strchr(cur, '\n');
        if (nl)
            *nl++ = '\0';

        num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
                     iface, dest, mask);
        cur = nl;

        if (num != 3) {
            VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
            continue;
        }

        if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
            VIR_DEBUG("Failed to convert network address %s to uint", dest);
            continue;
        }

        if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
            VIR_DEBUG("Failed to convert network mask %s to uint", mask);
            continue;
        }

        addr_val &= mask_val;

        for (i = 0;
             (ipdef = virNetworkDefGetIpByIndex(def, AF_INET, i));
             i++) {

            unsigned int net_dest;
            virSocketAddr netmask;

            if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
                VIR_WARN("Failed to get netmask of '%s'",
                         def->bridge);
                continue;
            }

            net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
                        netmask.data.inet4.sin_addr.s_addr);

            if ((net_dest == addr_val) &&
                (netmask.data.inet4.sin_addr.s_addr == mask_val)) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Network is already in use by interface %s"),
                               iface);
                ret = -1;
                goto out;
            }
        }
    }

 out:
    VIR_FREE(buf);
    return ret;
}
コード例 #27
0
ファイル: cpu_conf.c プロジェクト: rmarwaha/libvirt1
virCPUDefPtr
virCPUDefParseXML(const xmlNodePtr node,
                  xmlXPathContextPtr ctxt,
                  enum virCPUType mode)
{
    virCPUDefPtr def;
    xmlNodePtr *nodes = NULL;
    int n;
    unsigned int i;
    char *cpuMode;

    if (!xmlStrEqual(node->name, BAD_CAST "cpu")) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                          "%s",
                          _("XML does not contain expected 'cpu' element"));
        return NULL;
    }

    if (VIR_ALLOC(def) < 0) {
        virReportOOMError();
        return NULL;
    }

    if (mode == VIR_CPU_TYPE_AUTO) {
        if (virXPathBoolean("boolean(./arch)", ctxt)) {
            if (virXPathBoolean("boolean(./@match)", ctxt)) {
                virCPUReportError(VIR_ERR_XML_ERROR, "%s",
                        _("'arch' element element cannot be used inside 'cpu'"
                          " element with 'match' attribute'"));
                goto error;
            }
            def->type = VIR_CPU_TYPE_HOST;
        } else {
            def->type = VIR_CPU_TYPE_GUEST;
        }
    } else {
        def->type = mode;
    }

    if ((cpuMode = virXMLPropString(node, "mode"))) {
        if (def->type == VIR_CPU_TYPE_HOST) {
            VIR_FREE(cpuMode);
            virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                              _("Attribute mode is only allowed for guest CPU"));
            goto error;
        } else {
            def->mode = virCPUModeTypeFromString(cpuMode);

            if (def->mode < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                                  _("Invalid mode attribute '%s'"),
                                  cpuMode);
                VIR_FREE(cpuMode);
                goto error;
            }
            VIR_FREE(cpuMode);
        }
    } else {
        if (def->type == VIR_CPU_TYPE_HOST)
            def->mode = -1;
        else
            def->mode = VIR_CPU_MODE_CUSTOM;
    }

    if (def->type == VIR_CPU_TYPE_GUEST) {
        char *match = virXMLPropString(node, "match");

        if (!match) {
            if (virXPathBoolean("boolean(./model)", ctxt))
                def->match = VIR_CPU_MATCH_EXACT;
            else
                def->match = -1;
        } else {
            def->match = virCPUMatchTypeFromString(match);
            VIR_FREE(match);

            if (def->match < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Invalid match attribute for CPU specification"));
                goto error;
            }
        }
    }

    if (def->type == VIR_CPU_TYPE_HOST) {
        def->arch = virXPathString("string(./arch[1])", ctxt);
        if (!def->arch) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing CPU architecture"));
            goto error;
        }
    }

    if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
        def->type == VIR_CPU_TYPE_HOST) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                "%s", _("Missing CPU model name"));
        goto error;
    }

    if (def->type == VIR_CPU_TYPE_GUEST &&
        def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH &&
        virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
        const char *fallback;

        fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
        if (fallback) {
            def->fallback = virCPUFallbackTypeFromString(fallback);
            VIR_FREE(fallback);
            if (def->fallback < 0) {
                virCPUReportError(VIR_ERR_XML_ERROR, "%s",
                                  _("Invalid fallback attribute"));
                goto error;
            }
        }
    }

    def->vendor = virXPathString("string(./vendor[1])", ctxt);
    if (def->vendor && !def->model) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                "%s", _("CPU vendor specified without CPU model"));
        goto error;
    }

    if (virXPathNode("./topology[1]", ctxt)) {
        int ret;
        unsigned long ul;

        ret = virXPathULong("string(./topology[1]/@sockets)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'sockets' attribute in CPU topology"));
            goto error;
        }
        def->sockets = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@cores)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'cores' attribute in CPU topology"));
            goto error;
        }
        def->cores = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@threads)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'threads' attribute in CPU topology"));
            goto error;
        }
        def->threads = (unsigned int) ul;

        if (!def->sockets || !def->cores || !def->threads) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid CPU topology"));
            goto error;
        }
    }

    n = virXPathNodeSet("./feature", ctxt, &nodes);
    if (n < 0)
        goto error;

    if (n > 0) {
        if (!def->model) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Non-empty feature list specified without CPU model"));
            goto error;
        }

        if (VIR_RESIZE_N(def->features, def->nfeatures_max,
                         def->nfeatures, n) < 0)
            goto no_memory;
        def->nfeatures = n;
    }

    for (i = 0 ; i < n ; i++) {
        char *name;
        int policy; /* enum virDomainCPUFeaturePolicy */
        unsigned int j;

        if (def->type == VIR_CPU_TYPE_GUEST) {
            char *strpolicy;

            strpolicy = virXMLPropString(nodes[i], "policy");
            if (strpolicy == NULL)
                policy = VIR_CPU_FEATURE_REQUIRE;
            else
                policy = virCPUFeaturePolicyTypeFromString(strpolicy);
            VIR_FREE(strpolicy);

            if (policy < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Invalid CPU feature policy"));
                goto error;
            }
        } else {
            policy = -1;
        }

        if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) {
            VIR_FREE(name);
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid CPU feature name"));
            goto error;
        }

        for (j = 0 ; j < i ; j++) {
            if (STREQ(name, def->features[j].name)) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        _("CPU feature `%s' specified more than once"),
                        name);
                VIR_FREE(name);
                goto error;
            }
        }

        def->features[i].name = name;
        def->features[i].policy = policy;
    }

    if (virXPathNode("./numa[1]", ctxt)) {
        VIR_FREE(nodes);
        n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes);
        if (n <= 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("NUMA topology defined without NUMA cells"));
            goto error;
        }

        if (VIR_RESIZE_N(def->cells, def->ncells_max,
                         def->ncells, n) < 0)
            goto no_memory;

        def->ncells = n;

        for (i = 0 ; i < n ; i++) {
            char *cpus, *memory;
            int cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
            int ret, ncpus = 0;

            def->cells[i].cellid = i;
            cpus = virXMLPropString(nodes[i], "cpus");
            if (!cpus) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'cpus' attribute in NUMA cell"));
                goto error;
            }
            def->cells[i].cpustr = cpus;

            if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0)
                goto no_memory;

            ncpus = virDomainCpuSetParse(cpus, 0, def->cells[i].cpumask,
                                         cpumasklen);
            if (ncpus <= 0)
                goto error;
            def->cells_cpus += ncpus;

            memory = virXMLPropString(nodes[i], "memory");
            if (!memory) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'memory' attribute in NUMA cell"));
                goto error;
            }

            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
            if (ret == -1) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid 'memory' attribute in NUMA cell"));
                VIR_FREE(memory);
                goto error;
            }
            VIR_FREE(memory);
        }
    }

cleanup:
    VIR_FREE(nodes);
    return def;

no_memory:
    virReportOOMError();

error:
    virCPUDefFree(def);
    def = NULL;
    goto cleanup;
}
コード例 #28
0
ファイル: virhostcpu.c プロジェクト: unipolar/libvirt
int
virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
                               virArch arch,
                               unsigned int *cpus,
                               unsigned int *mhz,
                               unsigned int *nodes,
                               unsigned int *sockets,
                               unsigned int *cores,
                               unsigned int *threads)
{
    virBitmapPtr present_cpus_map = NULL;
    virBitmapPtr online_cpus_map = NULL;
    char line[1024];
    DIR *nodedir = NULL;
    struct dirent *nodedirent = NULL;
    int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
    int threads_per_subcore = 0;
    unsigned int node;
    int ret = -1;
    char *sysfs_nodedir = NULL;
    char *sysfs_cpudir = NULL;
    int direrr;

    *mhz = 0;
    *cpus = *nodes = *sockets = *cores = *threads = 0;

    /* Start with parsing CPU clock speed from /proc/cpuinfo */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
        if (ARCH_IS_X86(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "cpu MHz")) {
                char *p;
                unsigned int ui;

                buf += 7;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                    /* Accept trailing fractional part.  */
                    (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *mhz = ui;
            }
        } else if (ARCH_IS_PPC(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "clock")) {
                char *p;
                unsigned int ui;

                buf += 5;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                    /* Accept trailing fractional part.  */
                    (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *mhz = ui;
                /* No other interesting infos are available in /proc/cpuinfo.
                 * However, there is a line identifying processor's version,
                 * identification and machine, but we don't want it to be caught
                 * and parsed in next iteration, because it is not in expected
                 * format and thus lead to error. */
            }
        } else if (ARCH_IS_ARM(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "BogoMIPS")) {
                char *p;
                unsigned int ui;

                buf += 8;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                    /* Accept trailing fractional part.  */
                    && (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *mhz = ui;
            }
        } else if (ARCH_IS_S390(arch)) {
            /* s390x has no realistic value for CPU speed,
             * assign a value of zero to signify this */
            *mhz = 0;
        } else {
            VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your architecture");
            break;
        }
    }

    /* Get information about what CPUs are present in the host and what
     * CPUs are online, so that we don't have to so for each node */
    present_cpus_map = virHostCPUGetPresentBitmap();
    if (!present_cpus_map)
        goto cleanup;
    online_cpus_map = virHostCPUGetOnlineBitmap();
    if (!online_cpus_map)
        goto cleanup;

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
     * core, node, socket, thread and topology information from /sys
     */
    if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_system_path) < 0)
        goto cleanup;

    if (!(nodedir = opendir(sysfs_nodedir))) {
        /* the host isn't probably running a NUMA architecture */
        goto fallback;
    }

    /* PPC-KVM needs the secondary threads of a core to be offline on the
     * host. The kvm scheduler brings the secondary threads online in the
     * guest context. Moreover, P8 processor has split-core capability
     * where, there can be 1,2 or 4 subcores per core. The primaries of the
     * subcores alone will be online on the host for a subcore in the
     * host. Even though the actual threads per core for P8 processor is 8,
     * depending on the subcores_per_core = 1, 2 or 4, the threads per
     * subcore will vary accordingly to 8, 4 and 2 repectively.
     * So, On host threads_per_core what is arrived at from sysfs in the
     * current logic is actually the subcores_per_core. Threads per subcore
     * can only be obtained from the kvm device. For example, on P8 wih 1
     * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
     * will be online. The sysfs reflects this and in the current logic
     * variable 'threads' will be 4 which is nothing but subcores_per_core.
     * If the user tampers the cpu online/offline states using chcpu or other
     * means, then it is an unsupported configuration for kvm.
     * The code below tries to keep in mind
     *  - when the libvirtd is run inside a KVM guest or Phyp based guest.
     *  - Or on the kvm host where user manually tampers the cpu states to
     *    offline/online randomly.
     * On hosts other than POWER this will be 0, in which case a simpler
     * thread-counting logic will be used  */
    if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
        goto cleanup;

    /* If the subcore configuration is not valid, just pretend subcores
     * are not in use and count threads one by one */
    if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
        threads_per_subcore = 0;

    while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
        if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
            continue;

        (*nodes)++;

        if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
                        sysfs_system_path, nodedirent->d_name) < 0)
            goto cleanup;

        if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
                                            present_cpus_map,
                                            online_cpus_map,
                                            threads_per_subcore,
                                            &nodesockets, &nodecores,
                                            &nodethreads, &offline)) < 0)
            goto cleanup;

        VIR_FREE(sysfs_cpudir);

        *cpus += nodecpus;

        if (nodesockets > *sockets)
            *sockets = nodesockets;

        if (nodecores > *cores)
            *cores = nodecores;

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

    if (direrr < 0)
        goto cleanup;

    if (*cpus && *nodes)
        goto done;

 fallback:
    VIR_FREE(sysfs_cpudir);

    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
        goto cleanup;

    if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
                                        present_cpus_map,
                                        online_cpus_map,
                                        threads_per_subcore,
                                        &nodesockets, &nodecores,
                                        &nodethreads, &offline)) < 0)
        goto cleanup;

    *nodes = 1;
    *cpus = nodecpus;
    *sockets = nodesockets;
    *cores = nodecores;
    *threads = nodethreads;

 done:
    /* There should always be at least one cpu, socket, node, and thread. */
    if (*cpus == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
        goto cleanup;
    }

    if (*sockets == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
        goto cleanup;
    }

    if (*threads == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
        goto cleanup;
    }

    /* Now check if the topology makes sense. There are machines that don't
     * expose their real number of nodes or for example the AMD Bulldozer
     * architecture that exposes their Clustered integer core modules as both
     * threads and cores. This approach throws off our detection. Unfortunately
     * the nodeinfo structure isn't designed to carry the full topology so
     * we're going to lie about the detected topology to notify the user
     * to check the host capabilities for the actual topology. */
    if ((*nodes *
         *sockets *
         *cores *
         *threads) != (*cpus + offline)) {
        *nodes = 1;
        *sockets = 1;
        *cores = *cpus + offline;
        *threads = 1;
    }

    ret = 0;

 cleanup:
    /* don't shadow a more serious error */
    if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
        virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
        ret = -1;
    }

    virBitmapFree(present_cpus_map);
    virBitmapFree(online_cpus_map);
    VIR_FREE(sysfs_nodedir);
    VIR_FREE(sysfs_cpudir);
    return ret;
}
コード例 #29
0
ファイル: nodeinfo.c プロジェクト: intgr/libvirt
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                             const char *sysfs_dir,
                             virNodeInfoPtr nodeinfo)
{
    char line[1024];
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    unsigned int cpu;
    unsigned long core, sock, cur_threads;
    cpu_set_t core_mask;
    cpu_set_t socket_mask;
    int online;
    int ret = -1;
    char *sysfs_cpudir = NULL;
    unsigned int cpu_cores = 0;

    nodeinfo->cpus = 0;
    nodeinfo->mhz = 0;
    nodeinfo->cores = 0;

    /* Start with parsing /proc/cpuinfo; although it tends to have
     * fewer details.  Hyperthreads are ignored at this stage.  */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
# if defined(__x86_64__) || \
    defined(__amd64__)  || \
    defined(__i386__)
        char *buf = line;
        if (STRPREFIX(buf, "cpu MHz")) {
            char *p;
            unsigned int ui;

            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpu MHz from cpuinfo"));
                goto cleanup;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        }

        if (STRPREFIX(buf, "cpu cores")) {
            char *p;
            unsigned int ui;

            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpu cores from cpuinfo"));
                return -1;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                && (*p == '\0' || c_isspace(*p)))
                cpu_cores = ui;
         }
# elif defined(__powerpc__) || \
      defined(__powerpc64__)
        char *buf = line;
        if (STRPREFIX(buf, "clock")) {
            char *p;
            unsigned int ui;

            buf += 5;
            while (*buf && c_isspace(*buf))
                buf++;

            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpu MHz from cpuinfo"));
                goto cleanup;
            }

            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
            /* No other interesting infos are available in /proc/cpuinfo.
             * However, there is a line identifying processor's version,
             * identification and machine, but we don't want it to be caught
             * and parsed in next iteration, because it is not in expected
             * format and thus lead to error. */
        }
# else
#  warning Parser for /proc/cpuinfo needs to be adapted for your architecture
# endif
    }

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
     * core, node, socket, thread and topology information from /sys
     */
    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_dir) < 0) {
        virReportOOMError();
        goto cleanup;
    }
    cpudir = opendir(sysfs_cpudir);
    if (cpudir == NULL) {
        virReportSystemError(errno, _("cannot opendir %s"), sysfs_cpudir);
        goto cleanup;
    }

    CPU_ZERO(&core_mask);
    CPU_ZERO(&socket_mask);

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

        online = virNodeGetCpuValue(sysfs_cpudir, cpu, "online", true);
        if (online < 0) {
            closedir(cpudir);
            goto cleanup;
        }
        if (!online)
            continue;
        nodeinfo->cpus++;

        /* Parse core */
        core = virNodeGetCpuValue(sysfs_cpudir, cpu, "topology/core_id", false);
        if (!CPU_ISSET(core, &core_mask)) {
            CPU_SET(core, &core_mask);
            nodeinfo->cores++;
        }

        /* Parse socket */
        sock = virNodeParseSocket(sysfs_cpudir, cpu);
        if (!CPU_ISSET(sock, &socket_mask)) {
            CPU_SET(sock, &socket_mask);
            nodeinfo->sockets++;
        }

        cur_threads = virNodeCountThreadSiblings(sysfs_cpudir, cpu);
        if (cur_threads == 0) {
            closedir(cpudir);
            goto cleanup;
        }
        if (cur_threads > nodeinfo->threads)
            nodeinfo->threads = cur_threads;
    }
    if (errno) {
        virReportSystemError(errno,
                             _("problem reading %s"), sysfs_cpudir);
        closedir(cpudir);
        goto cleanup;
    }
    if (closedir(cpudir) < 0) {
        virReportSystemError(errno,
                             _("problem closing %s"), sysfs_cpudir);
        goto cleanup;
    }

    if ((nodeinfo->nodes = virNodeParseNode(sysfs_dir)) <= 0)
        goto cleanup;

    /* There should always be at least one cpu, socket, node, and thread. */
    if (nodeinfo->cpus == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no CPUs found"));
        goto cleanup;
    }
    if (nodeinfo->sockets == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no sockets found"));
        goto cleanup;
    }
    if (nodeinfo->threads == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no threads found"));
        goto cleanup;
    }

    /* Platform like AMD Magny Cours has two NUMA nodes each package, and
     * the two nodes share the same core ID set, it results in the cores
     * number calculated from sysfs is not the actual cores number. Use
     * "cpu cores" in /proc/cpuinfo as the cores number instead in this case.
     * More details about the problem:
     * https://www.redhat.com/archives/libvir-list/2012-May/msg00607.html
     */
    if (cpu_cores && (cpu_cores > nodeinfo->cores))
        nodeinfo->cores = cpu_cores;

    /* nodeinfo->sockets is supposed to be a number of sockets per NUMA node,
     * however if NUMA nodes are not composed of whole sockets, we just lie
     * about the number of NUMA nodes and force apps to check capabilities XML
     * for the actual NUMA topology.
     */
    if (nodeinfo->sockets % nodeinfo->nodes == 0)
        nodeinfo->sockets /= nodeinfo->nodes;
    else
        nodeinfo->nodes = 1;

    ret = 0;

cleanup:
    VIR_FREE(sysfs_cpudir);
    return ret;
}
コード例 #30
0
ファイル: lxc_native.c プロジェクト: tdaajames/libvirt
static int
lxcBlkioDeviceWalkCallback(const char *name, virConfValuePtr value, void *data)
{
    char **parts = NULL;
    virBlkioDevicePtr device = NULL;
    virDomainDefPtr def = data;
    size_t i = 0;
    char *path = NULL;
    int ret = -1;

    if (!STRPREFIX(name, "lxc.cgroup.blkio.") ||
            STREQ(name, "lxc.cgroup.blkio.weight")|| !value->str)
        return 0;

    if (!(parts = lxcStringSplit(value->str)))
        return -1;

    if (!parts[0] || !parts[1]) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("invalid %s value: '%s'"),
                       name, value->str);
        goto cleanup;
    }

    if (virAsprintf(&path, "/dev/block/%s", parts[0]) < 0)
        goto cleanup;

    /* Do we already have a device definition for this path?
     * Get that device or create a new one */
    for (i = 0; !device && i < def->blkio.ndevices; i++) {
        if (STREQ(def->blkio.devices[i].path, path))
            device = &def->blkio.devices[i];
    }
    if (!device) {
        if (VIR_EXPAND_N(def->blkio.devices, def->blkio.ndevices, 1) < 0)
            goto cleanup;
        device = &def->blkio.devices[def->blkio.ndevices - 1];
        device->path = path;
        path = NULL;
    }

    /* Set the value */
    if (STREQ(name, "lxc.cgroup.blkio.device_weight")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->weight) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse device weight: '%s'"), parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_bps_device")) {
        if (virStrToLong_ull(parts[1], NULL, 10, &device->rbps) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse read_bps_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_bps_device")) {
        if (virStrToLong_ull(parts[1], NULL, 10, &device->wbps) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse write_bps_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.read_iops_device")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->riops) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse read_iops_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else if (STREQ(name, "lxc.cgroup.blkio.throttle.write_iops_device")) {
        if (virStrToLong_ui(parts[1], NULL, 10, &device->wiops) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to parse write_iops_device: '%s'"),
                           parts[1]);
            goto cleanup;
        }
    } else {
        VIR_WARN("Unhandled blkio tune config: %s", name);
    }

    ret = 0;

 cleanup:
    virStringFreeList(parts);
    VIR_FREE(path);

    return ret;
}