void virNetClientRemoveStream(virNetClientPtr client, virNetClientStreamPtr st) { virNetClientLock(client); size_t i; for (i = 0 ; i < client->nstreams ; i++) { if (client->streams[i] == st) break; } if (i == client->nstreams) goto cleanup; if (client->nstreams > 1) { memmove(client->streams + i, client->streams + i + 1, sizeof(*client->streams) * (client->nstreams - (i + 1))); VIR_SHRINK_N(client->streams, client->nstreams, 1); } else { VIR_FREE(client->streams); client->nstreams = 0; } virNetClientStreamFree(st); cleanup: virNetClientUnlock(client); }
/* Used post dispatch to actually remove any handles that * were previously marked as deleted. This asynchronous * cleanup is needed to make dispatch re-entrant safe. */ static void virEventPollCleanupHandles(void) { size_t i; size_t gap; VIR_DEBUG("Cleanup %zu", eventLoop.handlesCount); /* Remove deleted entries, shuffling down remaining * entries as needed to form contiguous series */ for (i = 0; i < eventLoop.handlesCount;) { if (!eventLoop.handles[i].deleted) { i++; continue; } PROBE(EVENT_POLL_PURGE_HANDLE, "watch=%d", eventLoop.handles[i].watch); if (eventLoop.handles[i].ff) { virFreeCallback ff = eventLoop.handles[i].ff; void *opaque = eventLoop.handles[i].opaque; virMutexUnlock(&eventLoop.lock); ff(opaque); virMutexLock(&eventLoop.lock); } if ((i+1) < eventLoop.handlesCount) { memmove(eventLoop.handles+i, eventLoop.handles+i+1, sizeof(struct virEventPollHandle)*(eventLoop.handlesCount -(i+1))); } eventLoop.handlesCount--; } /* Release some memory if we've got a big chunk free */ gap = eventLoop.handlesAlloc - eventLoop.handlesCount; if (eventLoop.handlesCount == 0 || (gap > eventLoop.handlesCount && gap > EVENT_ALLOC_EXTENT)) { EVENT_DEBUG("Found %zu out of %zu handles slots used, releasing %zu", eventLoop.handlesCount, eventLoop.handlesAlloc, gap); VIR_SHRINK_N(eventLoop.handles, eventLoop.handlesAlloc, gap); } }
static int libxlMakePCIList(virDomainDefPtr def, libxl_domain_config *d_config) { virDomainHostdevDefPtr *l_hostdevs = def->hostdevs; size_t nhostdevs = def->nhostdevs; size_t npcidevs = 0; libxl_device_pci *x_pcidevs; size_t i, j; if (nhostdevs == 0) return 0; if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0) return -1; for (i = 0, j = 0; i < nhostdevs; i++) { if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) continue; libxl_device_pci_init(&x_pcidevs[j]); if (libxlMakePCI(l_hostdevs[i], &x_pcidevs[j]) < 0) goto error; npcidevs++; j++; } VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs); d_config->pcidevs = x_pcidevs; d_config->num_pcidevs = npcidevs; return 0; error: for (i = 0; i < npcidevs; i++) libxl_device_pci_dispose(&x_pcidevs[i]); VIR_FREE(x_pcidevs); return -1; }
static int qemuMonitorTestProcessCommandText(qemuMonitorTestPtr test, const char *cmdstr) { char *tmp; char *cmdname; int ret = -1; if (!(cmdname = strdup(cmdstr))) { virReportOOMError(); return -1; } if (!(tmp = strchr(cmdname, ' '))) { virReportError(VIR_ERR_INTERNAL_ERROR, "Cannot find command name in '%s'", cmdstr); goto cleanup; } *tmp = '\0'; if (test->nitems == 0 || STRNEQ(test->items[0]->command_name, cmdname)) { ret = qemuMonitorTestAddReponse(test, "unexpected command"); } else { ret = qemuMonitorTestAddReponse(test, test->items[0]->response); qemuMonitorTestItemFree(test->items[0]); if (test->nitems == 1) { VIR_FREE(test->items); test->nitems = 0; } else { memmove(test->items, test->items + 1, sizeof(test->items[0]) * (test->nitems - 1)); VIR_SHRINK_N(test->items, test->nitems, 1); } } cleanup: VIR_FREE(cmdname); return ret; }
/* * Processes a single line, looking for a matching expected * item to reply with, else replies with an error */ static int qemuMonitorTestProcessCommandJSON(qemuMonitorTestPtr test, const char *cmdstr) { virJSONValuePtr val; const char *cmdname; int ret = -1; if (!(val = virJSONValueFromString(cmdstr))) return -1; if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "Missing command name in %s", cmdstr); goto cleanup; } if (test->nitems == 0 || STRNEQ(test->items[0]->command_name, cmdname)) { ret = qemuMonitorTestAddReponse(test, "{ \"error\": " " { \"desc\": \"Unexpected command\", " " \"class\": \"UnexpectedCommand\" } }"); } else { ret = qemuMonitorTestAddReponse(test, test->items[0]->response); qemuMonitorTestItemFree(test->items[0]); if (test->nitems == 1) { VIR_FREE(test->items); test->nitems = 0; } else { memmove(test->items, test->items + 1, sizeof(test->items[0]) * (test->nitems - 1)); VIR_SHRINK_N(test->items, test->nitems, 1); } } cleanup: virJSONValueFree(val); return ret; }
static int libxlMakeNicList(virDomainDefPtr def, libxl_domain_config *d_config) { virDomainNetDefPtr *l_nics = def->nets; size_t nnics = def->nnets; libxl_device_nic *x_nics; size_t i, nvnics = 0; if (VIR_ALLOC_N(x_nics, nnics) < 0) return -1; for (i = 0; i < nnics; i++) { if (l_nics[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) continue; if (libxlMakeNic(def, l_nics[i], &x_nics[nvnics])) goto error; /* * The devid (at least right now) will not get initialized by * libxl in the setup case but is required for starting the * device-model. */ if (x_nics[nvnics].devid < 0) x_nics[nvnics].devid = nvnics; nvnics++; } VIR_SHRINK_N(x_nics, nnics, nnics - nvnics); d_config->nics = x_nics; d_config->num_nics = nnics; return 0; error: for (i = 0; i < nnics; i++) libxl_device_nic_dispose(&x_nics[i]); VIR_FREE(x_nics); return -1; }
static virshNetworkListPtr virshNetworkListCollect(vshControl *ctl, unsigned int flags) { virshNetworkListPtr list = vshMalloc(ctl, sizeof(*list)); size_t i; int ret; char **names = NULL; virNetworkPtr net; bool success = false; size_t deleted = 0; int persistent; int autostart; int nActiveNets = 0; int nInactiveNets = 0; int nAllNets = 0; virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ if ((ret = virConnectListAllNetworks(priv->conn, &list->nets, flags)) >= 0) { list->nnets = ret; goto finished; } /* check if the command is actually supported */ if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) goto fallback; if (last_error && last_error->code == VIR_ERR_INVALID_ARG) { /* try the new API again but mask non-guaranteed flags */ unsigned int newflags = flags & (VIR_CONNECT_LIST_NETWORKS_ACTIVE | VIR_CONNECT_LIST_NETWORKS_INACTIVE); vshResetLibvirtError(); if ((ret = virConnectListAllNetworks(priv->conn, &list->nets, newflags)) >= 0) { list->nnets = ret; goto filter; } } /* there was an error during the first or second call */ vshError(ctl, "%s", _("Failed to list networks")); goto cleanup; fallback: /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); /* Get the number of active networks */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { if ((nActiveNets = virConnectNumOfNetworks(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of active networks")); goto cleanup; } } /* Get the number of inactive networks */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)) { if ((nInactiveNets = virConnectNumOfDefinedNetworks(priv->conn)) < 0) { vshError(ctl, "%s", _("Failed to get the number of inactive networks")); goto cleanup; } } nAllNets = nActiveNets + nInactiveNets; if (nAllNets == 0) return list; names = vshMalloc(ctl, sizeof(char *) * nAllNets); /* Retrieve a list of active network names */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { if (virConnectListNetworks(priv->conn, names, nActiveNets) < 0) { vshError(ctl, "%s", _("Failed to list active networks")); goto cleanup; } } /* Add the inactive networks to the end of the name list */ if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) || VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) { if (virConnectListDefinedNetworks(priv->conn, &names[nActiveNets], nInactiveNets) < 0) { vshError(ctl, "%s", _("Failed to list inactive networks")); goto cleanup; } } list->nets = vshMalloc(ctl, sizeof(virNetworkPtr) * (nAllNets)); list->nnets = 0; /* get active networks */ for (i = 0; i < nActiveNets; i++) { if (!(net = virNetworkLookupByName(priv->conn, names[i]))) continue; list->nets[list->nnets++] = net; } /* get inactive networks */ for (i = 0; i < nInactiveNets; i++) { if (!(net = virNetworkLookupByName(priv->conn, names[i]))) continue; list->nets[list->nnets++] = net; } /* truncate networks that weren't found */ deleted = nAllNets - list->nnets; filter: /* filter list the list if the list was acquired by fallback means */ for (i = 0; i < list->nnets; i++) { net = list->nets[i]; /* persistence filter */ if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_PERSISTENT)) { if ((persistent = virNetworkIsPersistent(net)) < 0) { vshError(ctl, "%s", _("Failed to get network persistence info")); goto cleanup; } if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_PERSISTENT) && persistent) || (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_TRANSIENT) && !persistent))) goto remove_entry; } /* autostart filter */ if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_AUTOSTART)) { if (virNetworkGetAutostart(net, &autostart) < 0) { vshError(ctl, "%s", _("Failed to get network autostart state")); goto cleanup; } if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_AUTOSTART) && autostart) || (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART) && !autostart))) goto remove_entry; } /* the pool matched all filters, it may stay */ continue; remove_entry: /* the pool has to be removed as it failed one of the filters */ virNetworkFree(list->nets[i]); list->nets[i] = NULL; deleted++; } finished: /* sort the list */ if (list->nets && list->nnets) qsort(list->nets, list->nnets, sizeof(*list->nets), virshNetworkSorter); /* truncate the list if filter simulation deleted entries */ if (deleted) VIR_SHRINK_N(list->nets, list->nnets, deleted); success = true; cleanup: for (i = 0; i < nAllNets; i++) VIR_FREE(names[i]); VIR_FREE(names); if (!success) { virshNetworkListFree(list); list = NULL; } return list; }
static virshSecretListPtr virshSecretListCollect(vshControl *ctl, unsigned int flags) { virshSecretListPtr list = vshMalloc(ctl, sizeof(*list)); size_t i; int ret; virSecretPtr secret; bool success = false; size_t deleted = 0; int nsecrets = 0; char **uuids = NULL; virshControlPtr priv = ctl->privData; /* try the list with flags support (0.10.2 and later) */ if ((ret = virConnectListAllSecrets(priv->conn, &list->secrets, flags)) >= 0) { list->nsecrets = ret; goto finished; } /* check if the command is actually supported */ if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) goto fallback; /* there was an error during the call */ vshError(ctl, "%s", _("Failed to list node secrets")); goto cleanup; fallback: /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); if (flags) { vshError(ctl, "%s", _("Filtering is not supported by this libvirt")); goto cleanup; } nsecrets = virConnectNumOfSecrets(priv->conn); if (nsecrets < 0) { vshError(ctl, "%s", _("Failed to count secrets")); goto cleanup; } if (nsecrets == 0) return list; uuids = vshMalloc(ctl, sizeof(char *) * nsecrets); nsecrets = virConnectListSecrets(priv->conn, uuids, nsecrets); if (nsecrets < 0) { vshError(ctl, "%s", _("Failed to list secrets")); goto cleanup; } list->secrets = vshMalloc(ctl, sizeof(virSecretPtr) * (nsecrets)); list->nsecrets = 0; /* get the secrets */ for (i = 0; i < nsecrets; i++) { if (!(secret = virSecretLookupByUUIDString(priv->conn, uuids[i]))) continue; list->secrets[list->nsecrets++] = secret; } /* truncate secrets that weren't found */ deleted = nsecrets - list->nsecrets; finished: /* sort the list */ if (list->secrets && list->nsecrets) qsort(list->secrets, list->nsecrets, sizeof(*list->secrets), virshSecretSorter); /* truncate the list for not found secret objects */ if (deleted) VIR_SHRINK_N(list->secrets, list->nsecrets, deleted); success = true; cleanup: if (nsecrets > 0) { for (i = 0; i < nsecrets; i++) VIR_FREE(uuids[i]); VIR_FREE(uuids); } if (!success) { virshSecretListFree(list); list = NULL; } return list; }
static vshInterfaceListPtr vshInterfaceListCollect(vshControl *ctl, unsigned int flags) { vshInterfaceListPtr list = vshMalloc(ctl, sizeof(*list)); int i; int ret; char **activeNames = NULL; char **inactiveNames = NULL; virInterfacePtr iface; bool success = false; size_t deleted = 0; int nActiveIfaces = 0; int nInactiveIfaces = 0; int nAllIfaces = 0; /* try the list with flags support (0.10.2 and later) */ if ((ret = virConnectListAllInterfaces(ctl->conn, &list->ifaces, flags)) >= 0) { list->nifaces = ret; goto finished; } /* check if the command is actually supported */ if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) goto fallback; /* there was an error during the first or second call */ vshError(ctl, "%s", _("Failed to list interfaces")); goto cleanup; fallback: /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); if (flags & VIR_CONNECT_LIST_INTERFACES_ACTIVE) { nActiveIfaces = virConnectNumOfInterfaces(ctl->conn); if (nActiveIfaces < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); goto cleanup; } if (nActiveIfaces) { activeNames = vshMalloc(ctl, sizeof(char *) * nActiveIfaces); if ((nActiveIfaces = virConnectListInterfaces(ctl->conn, activeNames, nActiveIfaces)) < 0) { vshError(ctl, "%s", _("Failed to list active interfaces")); goto cleanup; } } } if (flags & VIR_CONNECT_LIST_INTERFACES_INACTIVE) { nInactiveIfaces = virConnectNumOfDefinedInterfaces(ctl->conn); if (nInactiveIfaces < 0) { vshError(ctl, "%s", _("Failed to list inactive interfaces")); goto cleanup; } if (nInactiveIfaces) { inactiveNames = vshMalloc(ctl, sizeof(char *) * nInactiveIfaces); if ((nInactiveIfaces = virConnectListDefinedInterfaces(ctl->conn, inactiveNames, nInactiveIfaces)) < 0) { vshError(ctl, "%s", _("Failed to list inactive interfaces")); goto cleanup; } } } nAllIfaces = nActiveIfaces + nInactiveIfaces; if (nAllIfaces == 0) { VIR_FREE(activeNames); VIR_FREE(inactiveNames); return list; } list->ifaces = vshMalloc(ctl, sizeof(virInterfacePtr) * (nAllIfaces)); list->nifaces = 0; /* get active interfaces */ for (i = 0; i < nActiveIfaces; i++) { if (!(iface = virInterfaceLookupByName(ctl->conn, activeNames[i]))) { vshResetLibvirtError(); continue; } list->ifaces[list->nifaces++] = iface; } /* get inactive interfaces */ for (i = 0; i < nInactiveIfaces; i++) { if (!(iface = virInterfaceLookupByName(ctl->conn, inactiveNames[i]))) { vshResetLibvirtError(); continue; } list->ifaces[list->nifaces++] = iface; } /* truncate interfaces that weren't found */ deleted = nAllIfaces - list->nifaces; finished: /* sort the list */ if (list->ifaces && list->nifaces) qsort(list->ifaces, list->nifaces, sizeof(*list->ifaces), vshInterfaceSorter); /* truncate the list if filter simulation deleted entries */ if (deleted) VIR_SHRINK_N(list->ifaces, list->nifaces, deleted); success = true; cleanup: for (i = 0; i < nActiveIfaces; i++) VIR_FREE(activeNames[i]); for (i = 0; i < nInactiveIfaces; i++) VIR_FREE(inactiveNames[i]); VIR_FREE(activeNames); VIR_FREE(inactiveNames); if (!success) { vshInterfaceListFree(list); list = NULL; } return list; }
/* * Handles read/write of monitor data on the monitor server side */ static void qemuMonitorTestIO(virNetSocketPtr sock, int events, void *opaque) { qemuMonitorTestPtr test = opaque; bool err = false; virMutexLock(&test->lock); if (events & VIR_EVENT_HANDLE_WRITABLE) { ssize_t ret; if ((ret = virNetSocketWrite(sock, test->outgoing, test->outgoingLength)) < 0) { err = true; goto cleanup; } memmove(test->outgoing, test->outgoing + ret, test->outgoingLength - ret); test->outgoingLength -= ret; if ((test->outgoingCapacity - test->outgoingLength) > 1024) VIR_SHRINK_N(test->outgoing, test->outgoingCapacity, 1024); } if (events & VIR_EVENT_HANDLE_READABLE) { ssize_t ret, used; char *t1, *t2; if ((test->incomingCapacity - test->incomingLength) < 1024) { if (VIR_EXPAND_N(test->incoming, test->incomingCapacity, 1024) < 0) { err = true; goto cleanup; } } if ((ret = virNetSocketRead(sock, test->incoming + test->incomingLength, (test->incomingCapacity - test->incomingLength) - 1)) < 0) { err = true; goto cleanup; } test->incomingLength += ret; test->incoming[test->incomingLength] = '\0'; /* Look to see if we've got a complete line, and * if so, handle that command */ t1 = test->incoming; while ((t2 = strstr(t1, "\r\n"))) { *t2 = '\0'; if (qemuMonitorTestProcessCommand(test, t1) < 0) { err = true; goto cleanup; } t1 = t2 + 2; } used = t1 - test->incoming; memmove(test->incoming, t1, test->incomingLength - used); test->incomingLength -= used; if ((test->incomingCapacity - test->incomingLength) > 1024) { VIR_SHRINK_N(test->incoming, test->incomingCapacity, 1024); } } if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) err = true; cleanup: if (err) { virNetSocketRemoveIOCallback(sock); virNetSocketClose(sock); virObjectUnref(test->client); test->client = NULL; } else { events = VIR_EVENT_HANDLE_READABLE; if (test->outgoingLength) events |= VIR_EVENT_HANDLE_WRITABLE; virNetSocketUpdateIOCallback(sock, events); } virMutexUnlock(&test->lock); }
static vshNodeDeviceListPtr vshNodeDeviceListCollect(vshControl *ctl, char **capnames, int ncapnames, unsigned int flags) { vshNodeDeviceListPtr list = vshMalloc(ctl, sizeof(*list)); int i; int ret; virNodeDevicePtr device; bool success = false; size_t deleted = 0; int ndevices = 0; char **names = NULL; /* try the list with flags support (0.10.2 and later) */ if ((ret = virConnectListAllNodeDevices(ctl->conn, &list->devices, flags)) >= 0) { list->ndevices = ret; goto finished; } /* check if the command is actually supported */ if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) goto fallback; /* there was an error during the call */ vshError(ctl, "%s", _("Failed to list node devices")); goto cleanup; fallback: /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); ndevices = virNodeNumOfDevices(ctl->conn, NULL, 0); if (ndevices < 0) { vshError(ctl, "%s", _("Failed to count node devices")); goto cleanup; } if (ndevices == 0) return list; names = vshMalloc(ctl, sizeof(char *) * ndevices); ndevices = virNodeListDevices(ctl->conn, NULL, names, ndevices, 0); if (ndevices < 0) { vshError(ctl, "%s", _("Failed to list node devices")); goto cleanup; } list->devices = vshMalloc(ctl, sizeof(virNodeDevicePtr) * (ndevices)); list->ndevices = 0; /* get the node devices */ for (i = 0; i < ndevices ; i++) { if (!(device = virNodeDeviceLookupByName(ctl->conn, names[i]))) continue; list->devices[list->ndevices++] = device; } /* truncate domains that weren't found */ deleted = ndevices - list->ndevices; if (!capnames) goto finished; /* filter the list if the list was acquired by fallback means */ for (i = 0; i < list->ndevices; i++) { char **caps = NULL; int ncaps = 0; bool match = false; device = list->devices[i]; if ((ncaps = virNodeDeviceNumOfCaps(device)) < 0) { vshError(ctl, "%s", _("Failed to get capability numbers " "of the device")); goto cleanup; } caps = vshMalloc(ctl, sizeof(char *) * ncaps); if ((ncaps = virNodeDeviceListCaps(device, caps, ncaps)) < 0) { vshError(ctl, "%s", _("Failed to get capability names of the device")); VIR_FREE(caps); goto cleanup; } /* Check if the device's capability matches with provied * capabilities. */ int j, k; for (j = 0; j < ncaps; j++) { for (k = 0; k < ncapnames; k++) { if (STREQ(caps[j], capnames[k])) { match = true; break; } } } VIR_FREE(caps); if (!match) goto remove_entry; /* the device matched all filters, it may stay */ continue; remove_entry: /* the device has to be removed as it failed one of the filters */ virNodeDeviceFree(list->devices[i]); list->devices[i] = NULL; deleted++; } finished: /* sort the list */ if (list->devices && list->ndevices) qsort(list->devices, list->ndevices, sizeof(*list->devices), vshNodeDeviceSorter); /* truncate the list if filter simulation deleted entries */ if (deleted) VIR_SHRINK_N(list->devices, list->ndevices, deleted); success = true; cleanup: for (i = 0; i < ndevices; i++) VIR_FREE(names[i]); VIR_FREE(names); if (!success) { vshNodeDeviceListFree(list); list = NULL; } return list; }
static vshStorageVolListPtr vshStorageVolListCollect(vshControl *ctl, virStoragePoolPtr pool, unsigned int flags) { vshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list)); size_t i; char **names = NULL; virStorageVolPtr vol = NULL; bool success = false; size_t deleted = 0; int nvols = 0; int ret = -1; /* try the list with flags support (0.10.2 and later) */ if ((ret = virStoragePoolListAllVolumes(pool, &list->vols, flags)) >= 0) { list->nvols = ret; goto finished; } /* check if the command is actually supported */ if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) goto fallback; /* there was an error during the call */ vshError(ctl, "%s", _("Failed to list volumes")); goto cleanup; fallback: /* fall back to old method (0.10.1 and older) */ vshResetLibvirtError(); /* Determine the number of volumes in the pool */ if ((nvols = virStoragePoolNumOfVolumes(pool)) < 0) { vshError(ctl, "%s", _("Failed to list storage volumes")); goto cleanup; } if (nvols == 0) { success = true; return list; } /* Retrieve the list of volume names in the pool */ names = vshCalloc(ctl, nvols, sizeof(*names)); if ((nvols = virStoragePoolListVolumes(pool, names, nvols)) < 0) { vshError(ctl, "%s", _("Failed to list storage volumes")); goto cleanup; } list->vols = vshMalloc(ctl, sizeof(virStorageVolPtr) * (nvols)); list->nvols = 0; /* get the vols */ for (i = 0; i < nvols; i++) { if (!(vol = virStorageVolLookupByName(pool, names[i]))) continue; list->vols[list->nvols++] = vol; } /* truncate the list for not found vols */ deleted = nvols - list->nvols; finished: /* sort the list */ if (list->vols && list->nvols) qsort(list->vols, list->nvols, sizeof(*list->vols), vshStorageVolSorter); if (deleted) VIR_SHRINK_N(list->vols, list->nvols, deleted); success = true; cleanup: if (nvols > 0) for (i = 0; i < nvols; i++) VIR_FREE(names[i]); VIR_FREE(names); if (!success) { vshStorageVolListFree(list); list = NULL; } return list; }