/** * virDriverLoadModuleFull: * @path: filename of module to load * @regfunc: name of the function that registers the module * @handle: Returns handle of the loaded library if not NULL * * Loads a loadable module named @path and calls the * registration function @regfunc. If @handle is not NULL the handle is returned * in the variable. Otherwise the handle is leaked so that the module stays * loaded forever. * * The module is automatically looked up in the appropriate place (git or * installed directory). * * Returns 0 on success, 1 if the module was not found and -1 on any error. */ int virDriverLoadModuleFull(const char *path, const char *regfunc, void **handle) { void *rethandle = NULL; int (*regsym)(void); int ret = -1; if (!(rethandle = virDriverLoadModuleFile(path))) { ret = 1; goto cleanup; } if (!(regsym = virDriverLoadModuleFunc(rethandle, regfunc))) goto cleanup; if ((*regsym)() < 0) { VIR_ERROR(_("Failed module registration %s"), regfunc); goto cleanup; } if (handle) VIR_STEAL_PTR(*handle, rethandle); else rethandle = NULL; ret = 0; cleanup: if (rethandle) dlclose(rethandle); return ret; }
static qemuBlockJobDataPtr qemuBlockJobDataNew(qemuBlockJobType type, const char *name) { qemuBlockJobDataPtr job = NULL; qemuBlockJobDataPtr ret = NULL; if (qemuBlockJobDataInitialize() < 0) return NULL; if (!(job = virObjectNew(qemuBlockJobDataClass))) return NULL; if (VIR_STRDUP(job->name, name) < 0) goto cleanup; job->state = QEMU_BLOCKJOB_STATE_NEW; job->newstate = -1; job->type = type; VIR_STEAL_PTR(ret, job); cleanup: virObjectUnref(job); return ret; }
/** * qemuBlockJobUpdate: * @driver: qemu driver * @vm: domain * @disk: domain disk * @error: error (output parameter) * * Update disk's mirror state in response to a block job event stored in * blockJobStatus by qemuProcessHandleBlockJob event handler. * * Returns the block job event processed or -1 if there was no pending event. */ int qemuBlockJobUpdate(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob asyncJob, virDomainDiskDefPtr disk, char **error) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); int status = diskPriv->blockJobStatus; if (error) *error = NULL; if (status != -1) { qemuBlockJobEventProcess(driver, vm, disk, asyncJob, diskPriv->blockJobType, diskPriv->blockJobStatus); diskPriv->blockJobStatus = -1; if (error) VIR_STEAL_PTR(*error, diskPriv->blockJobError); else VIR_FREE(diskPriv->blockJobError); } return status; }
int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, char **name, virDomainCapsCPUUsable usable, char ***blockers) { if (VIR_RESIZE_N(cpuModels->models, cpuModels->nmodels_max, cpuModels->nmodels, 1) < 0) return -1; cpuModels->models[cpuModels->nmodels].usable = usable; VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].name, *name); if (blockers) VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].blockers, *blockers); cpuModels->nmodels++; return 0; }
/** * virCPUDefStealModel: * * Move CPU model related parts virCPUDef from @src to @dst. If @keepVendor * is true, the function keeps the original vendor/vendor_id in @dst rather * than overwriting it with the values from @src. */ void virCPUDefStealModel(virCPUDefPtr dst, virCPUDefPtr src, bool keepVendor) { char *vendor = NULL; char *vendor_id = NULL; if (keepVendor) { VIR_STEAL_PTR(vendor, dst->vendor); VIR_STEAL_PTR(vendor_id, dst->vendor_id); } virCPUDefFreeModel(dst); VIR_STEAL_PTR(dst->model, src->model); VIR_STEAL_PTR(dst->features, src->features); dst->microcodeVersion = src->microcodeVersion; dst->nfeatures_max = src->nfeatures_max; src->nfeatures_max = 0; dst->nfeatures = src->nfeatures; src->nfeatures = 0; if (keepVendor) { dst->vendor = vendor; dst->vendor_id = vendor_id; } else { VIR_STEAL_PTR(dst->vendor, src->vendor); VIR_STEAL_PTR(dst->vendor_id, src->vendor_id); } }
static int adminDispatchConnectGetLoggingOutputs(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client ATTRIBUTE_UNUSED, virNetMessagePtr msg ATTRIBUTE_UNUSED, virNetMessageErrorPtr rerr, admin_connect_get_logging_outputs_args *args, admin_connect_get_logging_outputs_ret *ret) { char *outputs = NULL; int noutputs = 0; if ((noutputs = adminConnectGetLoggingOutputs(&outputs, args->flags) < 0)) { virNetMessageSaveError(rerr); return -1; } VIR_STEAL_PTR(ret->outputs, outputs); ret->noutputs = noutputs; return 0; }
/** * qemuCgroupEmulatorAllNodesAllow: * @cgroup: domain cgroup pointer * @retData: filled with structure used to roll back the operation * * Allows all NUMA nodes for the qemu emulator thread temporarily. This is * necessary when hotplugging cpus since it requires memory allocated in the * DMA region. Afterwards the operation can be reverted by * qemuCgroupEmulatorAllNodesRestore. * * Returns 0 on success -1 on error */ int qemuCgroupEmulatorAllNodesAllow(virCgroupPtr cgroup, qemuCgroupEmulatorAllNodesDataPtr *retData) { qemuCgroupEmulatorAllNodesDataPtr data = NULL; char *all_nodes_str = NULL; virBitmapPtr all_nodes = NULL; int ret = -1; if (!virNumaIsAvailable() || !virCgroupHasController(cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) return 0; if (!(all_nodes = virNumaGetHostMemoryNodeset())) goto cleanup; if (!(all_nodes_str = virBitmapFormat(all_nodes))) goto cleanup; if (VIR_ALLOC(data) < 0) goto cleanup; if (virCgroupNewThread(cgroup, VIR_CGROUP_THREAD_EMULATOR, 0, false, &data->emulatorCgroup) < 0) goto cleanup; if (virCgroupGetCpusetMems(data->emulatorCgroup, &data->emulatorMemMask) < 0 || virCgroupSetCpusetMems(data->emulatorCgroup, all_nodes_str) < 0) goto cleanup; VIR_STEAL_PTR(*retData, data); ret = 0; cleanup: VIR_FREE(all_nodes_str); virBitmapFree(all_nodes); qemuCgroupEmulatorAllNodesDataFree(data); return ret; }
/* * Parses CPU definition XML from a node pointed to by @xpath. If @xpath is * NULL, the current node of @ctxt is used (i.e., it is a shortcut to "."). * * Missing <cpu> element in the XML document is not considered an error unless * @xpath is NULL in which case the function expects it was provided with a * valid <cpu> element already. In other words, the function returns success * and sets @cpu to NULL if @xpath is not NULL and the node pointed to by * @xpath is not found. * * Returns 0 on success, -1 on error. */ int virCPUDefParseXML(xmlXPathContextPtr ctxt, const char *xpath, virCPUType type, virCPUDefPtr *cpu) { virCPUDefPtr def = NULL; xmlNodePtr *nodes = NULL; xmlNodePtr oldnode = ctxt->node; int n; size_t i; char *cpuMode; char *fallback = NULL; char *vendor_id = NULL; int ret = -1; *cpu = NULL; if (xpath && !(ctxt->node = virXPathNode(xpath, ctxt))) { ret = 0; goto cleanup; } if (!virXMLNodeNameEqual(ctxt->node, "cpu")) { virReportError(VIR_ERR_XML_ERROR, "%s", _("XML does not contain expected 'cpu' element")); goto cleanup; } if (VIR_ALLOC(def) < 0) goto cleanup; if (type == VIR_CPU_TYPE_AUTO) { if (virXPathBoolean("boolean(./arch)", ctxt)) { if (virXPathBoolean("boolean(./@match)", ctxt)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("'arch' element cannot be used inside 'cpu'" " element with 'match' attribute'")); goto cleanup; } def->type = VIR_CPU_TYPE_HOST; } else { def->type = VIR_CPU_TYPE_GUEST; } } else { def->type = type; } if ((cpuMode = virXMLPropString(ctxt->node, "mode"))) { if (def->type == VIR_CPU_TYPE_HOST) { VIR_FREE(cpuMode); virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Attribute mode is only allowed for guest CPU")); goto cleanup; } else { def->mode = virCPUModeTypeFromString(cpuMode); if (def->mode < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid mode attribute '%s'"), cpuMode); VIR_FREE(cpuMode); goto cleanup; } 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(ctxt->node, "match"); char *check; 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) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid match attribute for CPU " "specification")); goto cleanup; } } if ((check = virXMLPropString(ctxt->node, "check"))) { int value = virCPUCheckTypeFromString(check); VIR_FREE(check); if (value < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid check attribute for CPU " "specification")); goto cleanup; } def->check = value; } } if (def->type == VIR_CPU_TYPE_HOST) { char *arch = virXPathString("string(./arch[1])", ctxt); if (!arch) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing CPU architecture")); goto cleanup; } if ((def->arch = virArchFromString(arch)) == VIR_ARCH_NONE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown architecture %s"), arch); VIR_FREE(arch); goto cleanup; } VIR_FREE(arch); if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 && virXPathUInt("string(./microcode[1]/@version)", ctxt, &def->microcodeVersion) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("invalid microcode version")); goto cleanup; } } if (!(def->model = virXPathString("string(./model[1])", ctxt)) && def->type == VIR_CPU_TYPE_HOST) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing CPU model name")); goto cleanup; } if (def->type == VIR_CPU_TYPE_GUEST && def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) { if ((fallback = virXPathString("string(./model[1]/@fallback)", ctxt))) { if ((def->fallback = virCPUFallbackTypeFromString(fallback)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid fallback attribute")); goto cleanup; } } if ((vendor_id = virXPathString("string(./model[1]/@vendor_id)", ctxt))) { if (strlen(vendor_id) != VIR_CPU_VENDOR_ID_LENGTH) { virReportError(VIR_ERR_XML_ERROR, _("vendor_id must be exactly %d characters long"), VIR_CPU_VENDOR_ID_LENGTH); goto cleanup; } /* ensure that the string can be passed to qemu*/ if (strchr(vendor_id, ',')) { virReportError(VIR_ERR_XML_ERROR, "%s", _("vendor id is invalid")); goto cleanup; } def->vendor_id = vendor_id; vendor_id = NULL; } } def->vendor = virXPathString("string(./vendor[1])", ctxt); if (def->vendor && !def->model) { virReportError(VIR_ERR_XML_ERROR, "%s", _("CPU vendor specified without CPU model")); goto cleanup; } if (virXPathNode("./topology[1]", ctxt)) { unsigned long ul; if (virXPathULong("string(./topology[1]/@sockets)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'sockets' attribute in CPU topology")); goto cleanup; } def->sockets = (unsigned int) ul; if (virXPathULong("string(./topology[1]/@cores)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'cores' attribute in CPU topology")); goto cleanup; } def->cores = (unsigned int) ul; if (virXPathULong("string(./topology[1]/@threads)", ctxt, &ul) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'threads' attribute in CPU topology")); goto cleanup; } def->threads = (unsigned int) ul; if (!def->sockets || !def->cores || !def->threads) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid CPU topology")); goto cleanup; } } if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0) goto cleanup; if (n > 0) { if (!def->model && def->mode == VIR_CPU_MODE_CUSTOM) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Non-empty feature list specified without " "CPU model")); goto cleanup; } if (VIR_RESIZE_N(def->features, def->nfeatures_max, def->nfeatures, n) < 0) goto cleanup; def->nfeatures = n; } for (i = 0; i < n; i++) { char *name; int policy; /* enum virDomainCPUFeaturePolicy */ size_t 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) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid CPU feature policy")); goto cleanup; } } else { policy = -1; } if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { VIR_FREE(name); virReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid CPU feature name")); goto cleanup; } for (j = 0; j < i; j++) { if (STREQ(name, def->features[j].name)) { virReportError(VIR_ERR_XML_ERROR, _("CPU feature '%s' specified more than once"), name); VIR_FREE(name); goto cleanup; } } def->features[i].name = name; def->features[i].policy = policy; } if (virXPathInt("count(./cache)", ctxt, &n) < 0) { goto cleanup; } else if (n > 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("at most one CPU cache element may be specified")); goto cleanup; } else if (n == 1) { int level = -1; char *strmode; int mode; if (virXPathBoolean("boolean(./cache[1]/@level)", ctxt) == 1 && (virXPathInt("string(./cache[1]/@level)", ctxt, &level) < 0 || level < 1 || level > 3)) { virReportError(VIR_ERR_XML_ERROR, "%s", _("invalid CPU cache level, must be in range [1,3]")); goto cleanup; } if (!(strmode = virXPathString("string(./cache[1]/@mode)", ctxt)) || (mode = virCPUCacheModeTypeFromString(strmode)) < 0) { VIR_FREE(strmode); virReportError(VIR_ERR_XML_ERROR, "%s", _("missing or invalid CPU cache mode")); goto cleanup; } VIR_FREE(strmode); if (VIR_ALLOC(def->cache) < 0) goto cleanup; def->cache->level = level; def->cache->mode = mode; } VIR_STEAL_PTR(*cpu, def); ret = 0; cleanup: ctxt->node = oldnode; VIR_FREE(fallback); VIR_FREE(vendor_id); VIR_FREE(nodes); virCPUDefFree(def); return ret; }
static virSecretPtr secretDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) { virSecretPtr ret = NULL; virSecretObjPtr obj = NULL; virSecretDefPtr objDef; virSecretDefPtr backup = NULL; virSecretDefPtr def; virObjectEventPtr event = NULL; virCheckFlags(0, NULL); if (!(def = virSecretDefParseString(xml))) return NULL; if (virSecretDefineXMLEnsureACL(conn, def) < 0) goto cleanup; if (!(obj = virSecretObjListAdd(driver->secrets, def, driver->configDir, &backup))) goto cleanup; VIR_STEAL_PTR(objDef, def); if (!objDef->isephemeral) { if (backup && backup->isephemeral) { if (virSecretObjSaveData(obj) < 0) goto restore_backup; } if (virSecretObjSaveConfig(obj) < 0) { if (backup && backup->isephemeral) { /* Undo the virSecretObjSaveData() above; ignore errors */ virSecretObjDeleteData(obj); } goto restore_backup; } } else if (backup && !backup->isephemeral) { if (virSecretObjDeleteConfig(obj) < 0) goto restore_backup; virSecretObjDeleteData(obj); } /* Saved successfully - drop old values */ virSecretDefFree(backup); event = virSecretEventLifecycleNew(objDef->uuid, objDef->usage_type, objDef->usage_id, VIR_SECRET_EVENT_DEFINED, 0); ret = virGetSecret(conn, objDef->uuid, objDef->usage_type, objDef->usage_id); goto cleanup; restore_backup: /* If we have a backup, then secret was defined before, so just restore * the backup; otherwise, this is a new secret, thus remove it. */ if (backup) { virSecretObjSetDef(obj, backup); VIR_STEAL_PTR(def, objDef); } else { virSecretObjListRemove(driver->secrets, obj); virObjectUnref(obj); obj = NULL; } cleanup: virSecretDefFree(def); virSecretObjEndAPI(&obj); if (event) virObjectEventStateQueue(driver->secretEventState, event); return ret; }