Iterating over one level of children requires parsing all snapshots and their parents; a bit of code shuffling makes it pretty easy to do this as well. * tools/virsh.c (cmdSnapshotList): Add another fallback. --- Applies anywhere after 2.5/4, but again, easiest to test against the same version of libvirtd if applied before 3/4. tools/virsh.c | 46 +++++++++++++++++++++++++++++++--------------- 1 files changed, 31 insertions(+), 15 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 93e4528..232c9b8 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -13096,6 +13096,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) information needed, 1 for parent column */ int numsnaps; char **names = NULL; + char **parents = NULL; int actual = 0; int i; xmlDocPtr xml = NULL; @@ -13112,6 +13113,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) const char *from = NULL; virDomainSnapshotPtr start = NULL; bool emulate_from = false; + bool descendants = false; if (vshCommandOptString(cmd, "from", &from) < 0) { vshError(ctl, _("invalid from argument '%s'"), from); @@ -13155,25 +13157,27 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) goto cleanup; if (from) { + descendants = vshCommandOptBool(cmd, "descendants"); start = virDomainSnapshotLookupByName(dom, from, 0); if (!start) goto cleanup; - if (vshCommandOptBool(cmd, "descendants") || tree) { + if (descendants || tree) { flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; } numsnaps = virDomainSnapshotNumChildren(start, flags); - /* XXX Is it worth emulating --from without --tree on older servers? */ - if (tree) { - if (numsnaps >= 0) { - numsnaps++; - } else if (last_error->code == VIR_ERR_NO_SUPPORT) { - /* We can emulate --tree --from. */ + if (numsnaps < 0) { + /* XXX also want to emulate --descendants without --tree */ + if ((!descendants || tree) + last_error->code == VIR_ERR_NO_SUPPORT) { + /* We can emulate --from. */ virFreeError(last_error); last_error = NULL; emulate_from = true; flags &= ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS; numsnaps = virDomainSnapshotNum(dom, flags); } + } else if (tree) { + numsnaps++; } } else { numsnaps = virDomainSnapshotNum(dom, flags); @@ -13234,9 +13238,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) if (actual < 0) goto cleanup; - if (tree) { - char indentBuf[INDENT_BUFLEN]; - char **parents = vshCalloc(ctl, sizeof(char *), actual); + if (!tree) + qsort(&names[0], actual, sizeof(char*), namesorter); + + if (tree || emulate_from) { + parents = vshCalloc(ctl, sizeof(char *), actual); for (i = (from && !emulate_from); i < actual; i++) { /* free up memory from previous iterations of the loop */ if (snapshot) @@ -13250,6 +13256,9 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) } parents[i] = vshGetSnapshotParent(ctl, snapshot); } + } + if (tree) { + char indentBuf[INDENT_BUFLEN]; for (i = 0 ; i < actual ; i++) { memset(indentBuf, '\0', sizeof indentBuf); if (emulate_from ? STREQ(names[i], from) : !parents[i]) @@ -13263,16 +13272,19 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd) 0, indentBuf); } - for (i = 0 ; i < actual ; i++) - VIR_FREE(parents[i]); - VIR_FREE(parents); ret = true; goto cleanup; } else { - qsort(&names[0], actual, sizeof(char*), namesorter); + if (emulate_from && descendants) { + /* XXX emulate --descendants as well */ + goto cleanup; + } for (i = 0; i < actual; i++) { + if (emulate_from && STRNEQ_NULLABLE(parents[i], from)) + continue; + /* free up memory from previous iterations of the loop */ VIR_FREE(parent); VIR_FREE(state); @@ -13337,9 +13349,13 @@ cleanup: xmlXPathFreeContext(ctxt); xmlFreeDoc(xml); VIR_FREE(doc); - for (i = 0; i < actual; i++) + for (i = 0; i < actual; i++) { VIR_FREE(names[i]); + if (parents) + VIR_FREE(parents[i]); + } VIR_FREE(names); + VIR_FREE(parents); if (dom) virDomainFree(dom); -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list