Exemplo n.º 1
0
int
virNWFilterObjListLoadAllConfigs(virNWFilterObjListPtr nwfilters,
                                 const char *configDir)
{
    DIR *dir;
    struct dirent *entry;
    int ret = -1;
    int rc;

    if ((rc = virDirOpenIfExists(&dir, configDir)) <= 0)
        return rc;

    while ((ret = virDirRead(dir, &entry, configDir)) > 0) {
        virNWFilterObjPtr obj;

        if (!virFileStripSuffix(entry->d_name, ".xml"))
            continue;

        obj = virNWFilterObjListLoadConfig(nwfilters, configDir, entry->d_name);
        if (obj)
            virNWFilterObjUnlock(obj);
    }

    VIR_DIR_CLOSE(dir);
    return ret;
}
Exemplo n.º 2
0
static int openvzAssignUUIDs(void)
{
    DIR *dp;
    struct dirent *dent;
    char *conf_dir;
    int vpsid;
    char *ext;
    int ret = 0;

    conf_dir = openvzLocateConfDir();
    if (conf_dir == NULL)
        return -1;

    dp = opendir(conf_dir);
    if (dp == NULL) {
        VIR_FREE(conf_dir);
        return 0;
    }

    while ((ret = virDirRead(dp, &dent, conf_dir)) > 0) {
        if (virStrToLong_i(dent->d_name, &ext, 10, &vpsid) < 0 ||
            *ext++ != '.' ||
            STRNEQ(ext, "conf"))
            continue;
        if (vpsid > 0) /* '0.conf' belongs to the host, ignore it */
            openvzSetUUID(vpsid);
    }

    closedir(dp);
    VIR_FREE(conf_dir);
    return ret;
}
Exemplo n.º 3
0
/* Returns device name (e.g. "sdc") on success, or NULL
 * on failure.
 */
char *
virSCSIDeviceGetDevName(const char *sysfs_prefix,
                        const char *adapter,
                        unsigned int bus,
                        unsigned int target,
                        unsigned long long unit)
{
    DIR *dir = NULL;
    struct dirent *entry;
    char *path = NULL;
    char *name = NULL;
    unsigned int adapter_id;
    const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_DEVICES;

    if (virSCSIDeviceGetAdapterId(adapter, &adapter_id) < 0)
        return NULL;

    if (virAsprintf(&path,
                    "%s/%d:%u:%u:%llu/block",
                    prefix, adapter_id, bus, target, unit) < 0)
        return NULL;

    if (virDirOpen(&dir, path) < 0)
        goto cleanup;

    while (virDirRead(dir, &entry, path) > 0) {
        ignore_value(VIR_STRDUP(name, entry->d_name));
        break;
    }

 cleanup:
    VIR_DIR_CLOSE(dir);
    VIR_FREE(path);
    return name;
}
Exemplo n.º 4
0
static int parallelsFindVmVolumes(virStoragePoolObjPtr pool,
                                  virDomainObjPtr dom)
{
    parallelsDomObjPtr pdom = dom->privateData;
    DIR *dir;
    struct dirent *ent;
    char *diskPath = NULL, *diskDescPath = NULL;
    struct stat sb;
    int ret = -1;
    int direrr;

    if (!(dir = opendir(pdom->home))) {
        virReportSystemError(errno,
                             _("cannot open path '%s'"),
                             pdom->home);
        goto cleanup;
    }

    while ((direrr = virDirRead(dir, &ent, pdom->home)) > 0) {
        VIR_FREE(diskPath);
        VIR_FREE(diskDescPath);

        if (!(diskPath = virFileBuildPath(pdom->home, ent->d_name, NULL)))
            goto cleanup;

        if (lstat(diskPath, &sb) < 0) {
            virReportSystemError(errno,
                                 _("cannot stat path '%s'"),
                                 ent->d_name);
            goto cleanup;
        }

        if (!S_ISDIR(sb.st_mode))
            continue;

        if (!(diskDescPath = virFileBuildPath(diskPath,
                                              "DiskDescriptor", ".xml")))
            goto cleanup;

        if (!virFileExists(diskDescPath))
            continue;

        /* here we know, that ent->d_name is a disk image directory */

        if (parallelsAddDiskVolume(pool, dom, ent->d_name,
                                   diskPath, diskDescPath))
            goto cleanup;
    }
    if (direrr < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    VIR_FREE(diskPath);
    VIR_FREE(diskDescPath);
    closedir(dir);
    return ret;

}
Exemplo n.º 5
0
static int
testSchemaDir(const char *schema,
              virXMLValidatorPtr validator,
              const char *dir_path)
{
    DIR *dir = NULL;
    struct dirent *ent;
    int ret = 0;
    int rc;
    char *test_name = NULL;
    char *xml_path = NULL;
    struct testSchemaData data = {
        .validator = validator,
    };

    if (virDirOpen(&dir, dir_path) < 0)
        return -1;

    while ((rc = virDirRead(dir, &ent, dir_path)) > 0) {
        if (!virStringHasSuffix(ent->d_name, ".xml"))
            continue;
        if (ent->d_name[0] == '.')
            continue;

        if (virAsprintf(&xml_path, "%s/%s", dir_path, ent->d_name) < 0)
            goto cleanup;

        if (virAsprintf(&test_name, "Checking %s against %s",
                        ent->d_name, schema) < 0)
            goto cleanup;

        data.xml_path = xml_path;
        if (virTestRun(test_name, testSchemaFile, &data) < 0)
            ret = -1;

        VIR_FREE(test_name);
        VIR_FREE(xml_path);
    }

    if (rc < 0)
        ret = -1;

 cleanup:
    VIR_FREE(test_name);
    VIR_FREE(xml_path);
    VIR_DIR_CLOSE(dir);
    return ret;
}
Exemplo n.º 6
0
int virProcessGetPids(pid_t pid, size_t *npids, pid_t **pids)
{
    int ret = -1;
    char *taskPath = NULL;
    DIR *dir = NULL;
    int value;
    struct dirent *ent;

    *npids = 0;
    *pids = NULL;

    if (virAsprintf(&taskPath, "/proc/%llu/task",
                    (unsigned long long)pid) < 0)
        goto cleanup;

    if (!(dir = opendir(taskPath)))
        goto cleanup;

    while ((value = virDirRead(dir, &ent, taskPath)) > 0) {
        long long tmp;
        pid_t tmp_pid;

        /* Skip . and .. */
        if (STRPREFIX(ent->d_name, "."))
            continue;

        if (virStrToLong_ll(ent->d_name, NULL, 10, &tmp) < 0)
            goto cleanup;
        tmp_pid = tmp;

        if (VIR_APPEND_ELEMENT(*pids, *npids, tmp_pid) < 0)
            goto cleanup;
    }

    if (value < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    if (dir)
        closedir(dir);
    VIR_FREE(taskPath);
    if (ret < 0)
        VIR_FREE(*pids);
    return ret;
}
Exemplo n.º 7
0
int virProcessGetPids(pid_t pid, size_t *npids, pid_t **pids)
{
    int ret = -1;
    char *taskPath = NULL;
    DIR *dir = NULL;
    int value;
    struct dirent *ent;

    *npids = 0;
    *pids = NULL;

    if (virAsprintf(&taskPath, "/proc/%llu/task",
                    (unsigned long long)pid) < 0)
        goto cleanup;

    if (virDirOpen(&dir, taskPath) < 0)
        goto cleanup;

    while ((value = virDirRead(dir, &ent, taskPath)) > 0) {
        long long tmp;
        pid_t tmp_pid;

        if (virStrToLong_ll(ent->d_name, NULL, 10, &tmp) < 0)
            goto cleanup;
        tmp_pid = tmp;

        if (VIR_APPEND_ELEMENT(*pids, *npids, tmp_pid) < 0)
            goto cleanup;
    }

    if (value < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    VIR_DIR_CLOSE(dir);
    VIR_FREE(taskPath);
    if (ret < 0)
        VIR_FREE(*pids);
    return ret;
}
static int
virStorageBackendISCSIGetHostNumber(const char *sysfs_path,
                                    uint32_t *host)
{
    int retval = 0;
    DIR *sysdir = NULL;
    struct dirent *dirent = NULL;
    int direrr;

    VIR_DEBUG("Finding host number from '%s'", sysfs_path);

    virFileWaitForDevices();

    sysdir = opendir(sysfs_path);

    if (sysdir == NULL) {
        virReportSystemError(errno,
                             _("Failed to opendir path '%s'"), sysfs_path);
        retval = -1;
        goto out;
    }

    while ((direrr = virDirRead(sysdir, &dirent, sysfs_path)) > 0) {
        if (STREQLEN(dirent->d_name, "target", strlen("target"))) {
            if (sscanf(dirent->d_name,
                       "target%u:", host) != 1) {
                VIR_DEBUG("Failed to parse target '%s'", dirent->d_name);
                retval = -1;
                break;
            }
        }
    }
    if (direrr < 0)
        retval = -1;

    closedir(sysdir);
out:
    return retval;
}
Exemplo n.º 9
0
static int
parallelsFindVolumes(virStoragePoolObjPtr pool)
{
    DIR *dir;
    struct dirent *ent;
    char *path = NULL;
    int ret = -1;
    int direrr;

    if (!(dir = opendir(pool->def->target.path))) {
        virReportSystemError(errno,
                             _("cannot open path '%s'"),
                             pool->def->target.path);
        return -1;
    }

    while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
        if (!virFileHasSuffix(ent->d_name, ".xml"))
            continue;

        if (!(path = virFileBuildPath(pool->def->target.path,
                                      ent->d_name, NULL)))
            goto cleanup;
        if (!parallelsStorageVolDefineXML(pool, NULL, path, false))
            goto cleanup;

        VIR_FREE(path);
    }
    if (direrr < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    VIR_FREE(path);
    closedir(dir);
    return ret;

}
Exemplo n.º 10
0
/**
 * 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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
static virUSBDeviceListPtr
virUSBDeviceSearch(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;
    virUSBDeviceListPtr list = NULL, ret = NULL;
    virUSBDevicePtr usb;
    int direrr;

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

    if (virDirOpen(&dir, USB_SYSFS "/devices") < 0)
        goto cleanup;

    while ((direrr = virDirRead(dir, &de, USB_SYSFS "/devices")) > 0) {
        unsigned int found_prod, found_vend, found_bus, found_devno;
        char *tmpstr = de->d_name;

        if (strchr(de->d_name, ':'))
            continue;

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

        if (virUSBSysReadFile("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 (virUSBSysReadFile("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 = virUSBDeviceNew(found_bus, found_devno, vroot);
        if (!usb)
            goto cleanup;

        if (virUSBDeviceListAdd(list, usb) < 0) {
            virUSBDeviceFree(usb);
            goto cleanup;
        }

        if (found)
            break;
    }
    if (direrr < 0)
        goto cleanup;
    ret = list;

 cleanup:
    VIR_DIR_CLOSE(dir);
    if (!ret)
        virObjectUnref(list);
    return ret;
}
Exemplo n.º 14
0
/**
 * xenInotifyOpen:
 * @conn: pointer to the connection block
 * @name: URL for the target, NULL for local
 * @flags: combination of virDrvOpenFlag(s)
 *
 * Connects and starts listening for inotify events
 *
 * Returns 0 or -1 in case of error.
 */
int
xenInotifyOpen(virConnectPtr conn,
               virConnectAuthPtr auth ATTRIBUTE_UNUSED,
               unsigned int flags)
{
    DIR *dh;
    struct dirent *ent;
    char *path;
    xenUnifiedPrivatePtr priv = conn->privateData;
    int direrr;
    time_t now = time(NULL);

    virCheckFlags(VIR_CONNECT_RO, -1);

    if (priv->configDir) {
        priv->useXenConfigCache = 1;
    } else {
        /* /var/lib/xend/domains/<uuid>/config.sxp */
        priv->configDir = XEND_DOMAINS_DIR;
        priv->useXenConfigCache = 0;

        if (VIR_ALLOC(priv->configInfoList) < 0)
            return -1;

        /* populate initial list */
        if (virDirOpen(&dh, priv->configDir) < 0)
            return -1;

        while ((direrr = virDirRead(dh, &ent, priv->configDir)) > 0) {
            if (STRPREFIX(ent->d_name, "."))
                continue;

            /* Build the full file path */
            if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) {
                VIR_DIR_CLOSE(dh);
                return -1;
            }

            if (xenInotifyAddDomainConfigInfo(conn, path, now) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("Error adding file to config list"));
                VIR_DIR_CLOSE(dh);
                VIR_FREE(path);
                return -1;
            }

            VIR_FREE(path);
        }
        VIR_DIR_CLOSE(dh);
        if (direrr < 0)
            return -1;
    }

    if ((priv->inotifyFD = inotify_init()) < 0) {
        virReportSystemError(errno,
                             "%s", _("initializing inotify"));
        return -1;
    }

    VIR_DEBUG("Adding a watch on %s", priv->configDir);
    if (inotify_add_watch(priv->inotifyFD,
                          priv->configDir,
                          IN_CREATE |
                          IN_CLOSE_WRITE | IN_DELETE |
                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
        virReportSystemError(errno,
                             _("adding watch on %s"),
                             priv->configDir);
        return -1;
    }

    VIR_DEBUG("Building initial config cache");
    if (priv->useXenConfigCache &&
        xenXMConfigCacheRefresh(conn) < 0) {
        VIR_DEBUG("Failed to enable XM config cache %s", conn->err.message);
        return -1;
    }

    VIR_DEBUG("Registering with event loop");
    /* Add the handle for monitoring */
    if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
                                                xenInotifyEvent, conn, NULL)) < 0) {
        VIR_DEBUG("Failed to add inotify handle, disabling events");
    }

    return 0;
}