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; }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
/** * 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; }
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; }
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; }
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; }
/** * 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; }