tools/virsh.c:
* vshStorageVolSorter to sort storage vols by name
* vshStorageVolumeListFree to free the volume objects list
* vshStorageVolumeListCollect to collect the volume objects, trying
to use new API first, fall back to older APIs if it's not supported.
---
tools/virsh.c | 197 +++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 150 insertions(+), 47 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 7d7c9ca..9556e16 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -12793,6 +12793,133 @@ cmdVolDumpXML(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+static int
+vshStorageVolSorter(const void *a, const void *b)
+{
+ virStorageVolPtr *va = (virStorageVolPtr *) a;
+ virStorageVolPtr *vb = (virStorageVolPtr *) b;
+
+ if (*va && !*vb)
+ return -1;
+
+ if (!*va)
+ return *vb != NULL;
+
+ return strcasecmp(virStorageVolGetName(*va),
+ virStorageVolGetName(*vb));
+}
+
+struct vshStorageVolList {
+ virStorageVolPtr *vols;
+ size_t nvols;
+};
+typedef struct vshStorageVolList *vshStorageVolListPtr;
+
+static void
+vshStorageVolListFree(vshStorageVolListPtr list)
+{
+ int i;
+
+ if (list && list->vols) {
+ for (i = 0; i < list->nvols; i++) {
+ if (list->vols[i])
+ virStorageVolFree(list->vols[i]);
+ }
+ VIR_FREE(list->vols);
+ }
+ VIR_FREE(list);
+}
+
+static vshStorageVolListPtr
+vshStorageVolListCollect(vshControl *ctl,
+ virStoragePoolPtr pool,
+ unsigned int flags)
+{
+ vshStorageVolListPtr list = vshMalloc(ctl, sizeof(*list));
+ int 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.9.14 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) {
+ virFreeError(last_error);
+ last_error = NULL;
+ 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.9.13 and older) */
+ virResetLastError();
+
+ /* 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:
+ for (i = 0; i < nvols; i++)
+ VIR_FREE(names[i]);
+ VIR_FREE(names);
+
+ if (!success) {
+ vshStorageVolListFree(list);
+ list = NULL;
+ }
+
+ return list;
+}
/*
* "vol-list" command
@@ -12814,14 +12941,13 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
{
virStorageVolInfo volumeInfo;
virStoragePoolPtr pool;
- char **activeNames = NULL;
char *outputStr = NULL;
const char *unit;
double val;
bool details = vshCommandOptBool(cmd, "details");
- int numVolumes = 0, i;
+ int i;
int ret;
- bool functionReturn;
+ bool functionReturn = false;
int stringLength = 0;
size_t allocStrLength = 0, capStrLength = 0;
size_t nameStrLength = 0, pathStrLength = 0;
@@ -12833,6 +12959,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
char *type;
};
struct volInfoText *volInfoTexts = NULL;
+ vshStorageVolListPtr list = NULL;
/* Check the connection to libvirtd daemon is still working */
if (!vshConnectionUsability(ctl, ctl->conn))
@@ -12842,38 +12969,16 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
if (!(pool = vshCommandOptPool(ctl, cmd, "pool", NULL)))
return false;
- /* Determine the number of volumes in the pool */
- numVolumes = virStoragePoolNumOfVolumes(pool);
-
- if (numVolumes < 0) {
- vshError(ctl, "%s", _("Failed to list storage volumes"));
- virStoragePoolFree(pool);
- return false;
- }
-
- /* Retrieve the list of volume names in the pool */
- if (numVolumes > 0) {
- activeNames = vshCalloc(ctl, numVolumes, sizeof(*activeNames));
- if ((numVolumes = virStoragePoolListVolumes(pool, activeNames,
- numVolumes)) < 0) {
- vshError(ctl, "%s", _("Failed to list active vols"));
- VIR_FREE(activeNames);
- virStoragePoolFree(pool);
- return false;
- }
-
- /* Sort the volume names */
- qsort(&activeNames[0], numVolumes, sizeof(*activeNames), vshNameSorter);
+ if (!(list = vshStorageVolListCollect(ctl, pool, 0)))
+ goto cleanup;
- /* Set aside memory for volume information pointers */
- volInfoTexts = vshCalloc(ctl, numVolumes, sizeof(*volInfoTexts));
- }
+ if (list->nvols > 0)
+ volInfoTexts = vshCalloc(ctl, list->nvols, sizeof(*volInfoTexts));
/* Collect the rest of the volume information for display */
- for (i = 0; i < numVolumes; i++) {
+ for (i = 0; i < list->nvols; i++) {
/* Retrieve volume info */
- virStorageVolPtr vol = virStorageVolLookupByName(pool,
- activeNames[i]);
+ virStorageVolPtr vol = list->vols[i];
/* Retrieve the volume path */
if ((volInfoTexts[i].path = virStorageVolGetPath(vol)) == NULL) {
@@ -12931,7 +13036,7 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
*/
/* Keep the length of name string if longest so far */
- stringLength = strlen(activeNames[i]);
+ stringLength = strlen(virStorageVolGetName(list->vols[i]));
if (stringLength > nameStrLength)
nameStrLength = stringLength;
@@ -12955,9 +13060,6 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
if (stringLength > allocStrLength)
allocStrLength = stringLength;
}
-
- /* Cleanup memory allocation */
- virStorageVolFree(vol);
}
/* If the --details option wasn't selected, we output the volume
@@ -12970,8 +13072,8 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
/* The old output format */
vshPrintExtra(ctl, "%-20s %-40s\n", _("Name"),
_("Path"));
vshPrintExtra(ctl, "-----------------------------------------\n");
- for (i = 0; i < numVolumes; i++) {
- vshPrint(ctl, "%-20s %-40s\n", activeNames[i],
+ for (i = 0; i < list->nvols; i++) {
+ vshPrint(ctl, "%-20s %-40s\n",
virStorageVolGetName(list->vols[i]),
volInfoTexts[i].path);
}
@@ -13042,9 +13144,9 @@ cmdVolList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
vshPrintExtra(ctl, "\n");
/* Display the volume info rows */
- for (i = 0; i < numVolumes; i++) {
+ for (i = 0; i < list->nvols; i++) {
vshPrint(ctl, outputStr,
- activeNames[i],
+ virStorageVolGetName(list->vols[i]),
volInfoTexts[i].path,
volInfoTexts[i].type,
volInfoTexts[i].capacity,
@@ -13072,20 +13174,21 @@ asprintf_failure:
cleanup:
/* Safely free the memory allocated in this function */
- for (i = 0; i < numVolumes; i++) {
- /* Cleanup the memory for one volume info structure per loop */
- VIR_FREE(volInfoTexts[i].path);
- VIR_FREE(volInfoTexts[i].type);
- VIR_FREE(volInfoTexts[i].capacity);
- VIR_FREE(volInfoTexts[i].allocation);
- VIR_FREE(activeNames[i]);
+ if (list && list->nvols) {
+ for (i = 0; i < list->nvols; i++) {
+ /* Cleanup the memory for one volume info structure per loop */
+ VIR_FREE(volInfoTexts[i].path);
+ VIR_FREE(volInfoTexts[i].type);
+ VIR_FREE(volInfoTexts[i].capacity);
+ VIR_FREE(volInfoTexts[i].allocation);
+ }
}
/* Cleanup remaining memory */
VIR_FREE(outputStr);
VIR_FREE(volInfoTexts);
- VIR_FREE(activeNames);
virStoragePoolFree(pool);
+ vshStorageVolListFree(list);
/* Return the desired value */
return functionReturn;
--
1.7.7.3