[libvirt] [PATCH] qemuDomainAttach: Initialize pidfile variable

2011-10-09 Thread Michal Privoznik
If parsing qemu command line fails (e.g. because of non-existing
process number supplied), we jump to cleanup label where we free
pidfile. Therefore it needs to be initialized. Otherwise we free
random pointer.
---

Pushing under trivial rule.

 src/qemu/qemu_driver.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2e6f3e4..5588d93 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10179,7 +10179,7 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn,
 virDomainPtr dom = NULL;
 virDomainChrSourceDefPtr monConfig = NULL;
 bool monJSON = false;
-char *pidfile;
+char *pidfile = NULL;
 
 virCheckFlags(0, NULL);
 
-- 
1.7.3.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Qemu/KVM guest boots 2x slower with vhost_net

2011-10-09 Thread Reeted

On 10/05/11 01:12, Reeted wrote:

.
I found that virtual machines in my host booted 2x slower ... to the 
vhost_net presence

...


Just a small update,

Firstly: I cannot reproduce any slowness after boot by doing:

# time /etc/init.d/chrony restart
Restarting time daemon: Starting /usr/sbin/chronyd...
chronyd is running and online.
real0m3.022s
user0m0.000s
sys 0m0.000s

since this is a network service I expected it to show the problem, but 
it doesn't. It takes exactly same time with and without vhost_net.



Secondly, vhost_net appears to work correctly, because I have performed 
a NPtcp performance test between two guests in the same host, and these 
are the results:


vhost_net deactivated for both hosts:

NPtcp -h 192.168.7.81
Send and receive buffers are 16384 and 87380 bytes
(A bug in Linux doubles the requested buffer sizes)
Now starting the main loop
0:   1 bytes917 times --  0.08 Mbps in  92.07 usec
1:   2 bytes   1086 times --  0.18 Mbps in  86.04 usec
2:   3 bytes   1162 times --  0.27 Mbps in  85.08 usec
3:   4 bytes783 times --  0.36 Mbps in  85.34 usec
4:   6 bytes878 times --  0.54 Mbps in  85.42 usec
5:   8 bytes585 times --  0.72 Mbps in  85.31 usec
6:  12 bytes732 times --  1.07 Mbps in  85.52 usec
7:  13 bytes487 times --  1.16 Mbps in  85.52 usec
8:  16 bytes539 times --  1.43 Mbps in  85.26 usec
9:  19 bytes659 times --  1.70 Mbps in  85.43 usec
10:  21 bytes739 times --  1.77 Mbps in  90.71 usec
11:  24 bytes734 times --  2.13 Mbps in  86.13 usec
12:  27 bytes822 times --  2.22 Mbps in  92.80 usec
13:  29 bytes478 times --  2.35 Mbps in  94.02 usec
14:  32 bytes513 times --  2.60 Mbps in  93.75 usec
15:  35 bytes566 times --  3.15 Mbps in  84.77 usec
16:  45 bytes674 times --  4.01 Mbps in  85.56 usec
17:  48 bytes779 times --  4.32 Mbps in  84.70 usec
18:  51 bytes811 times --  4.61 Mbps in  84.32 usec
19:  61 bytes465 times --  5.08 Mbps in  91.57 usec
20:  64 bytes537 times --  5.22 Mbps in  93.46 usec
21:  67 bytes551 times --  5.73 Mbps in  89.20 usec
22:  93 bytes602 times --  8.28 Mbps in  85.73 usec
23:  96 bytes777 times --  8.45 Mbps in  86.70 usec
24:  99 bytes780 times --  8.71 Mbps in  86.72 usec
25: 125 bytes419 times -- 11.06 Mbps in  86.25 usec
26: 128 bytes575 times -- 11.38 Mbps in  85.80 usec
27: 131 bytes591 times -- 11.60 Mbps in  86.17 usec
28: 189 bytes602 times -- 16.55 Mbps in  87.14 usec
29: 192 bytes765 times -- 16.80 Mbps in  87.19 usec
30: 195 bytes770 times -- 17.11 Mbps in  86.94 usec
31: 253 bytes401 times -- 22.04 Mbps in  87.59 usec
32: 256 bytes568 times -- 22.64 Mbps in  86.25 usec
33: 259 bytes584 times -- 22.68 Mbps in  87.12 usec
34: 381 bytes585 times -- 33.19 Mbps in  87.58 usec
35: 384 bytes761 times -- 33.54 Mbps in  87.36 usec
36: 387 bytes766 times -- 33.91 Mbps in  87.08 usec
37: 509 bytes391 times -- 44.23 Mbps in  87.80 usec
38: 512 bytes568 times -- 44.70 Mbps in  87.39 usec
39: 515 bytes574 times -- 45.21 Mbps in  86.90 usec
40: 765 bytes580 times -- 66.05 Mbps in  88.36 usec
41: 768 bytes754 times -- 66.73 Mbps in  87.81 usec
42: 771 bytes760 times -- 67.02 Mbps in  87.77 usec
43:1021 bytes384 times -- 88.04 Mbps in  88.48 usec
44:1024 bytes564 times -- 88.30 Mbps in  88.48 usec
45:1027 bytes566 times -- 88.63 Mbps in  88.40 usec
46:1533 bytes568 times -- 71.75 Mbps in 163.00 usec
47:1536 bytes408 times -- 72.11 Mbps in 162.51 usec
48:1539 bytes410 times -- 71.71 Mbps in 163.75 usec
49:2045 bytes204 times -- 95.40 Mbps in 163.55 usec
50:2048 bytes305 times -- 95.26 Mbps in 164.02 usec
51:2051 bytes305 times -- 95.33 Mbps in 164.14 usec
52:3069 bytes305 times --141.16 Mbps in 165.87 usec
53:3072 bytes401 times --142.19 Mbps in 164.83 usec
54:3075 bytes404 times --150.68 Mbps in 155.70 usec
55:4093 bytes214 times --192.36 Mbps in 162.33 usec
56:4096 bytes307 times --193.21 Mbps in 161.74 usec
  

Re: [libvirt] [PATCH 6/7] Rewrite all the DTrace/SystemTAP probing

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 12:01:18PM -0600, Eric Blake wrote:
 On 10/07/2011 09:56 AM, Daniel P. Berrange wrote:
[...]
 It's big, but useful, and I think that we can clean up the fallout
 as separate patches as we port it to more compilation environments
 (VPATH, older systemtap headers, etc.).  I'm okay giving ACK.

 It would be good to test for portability, like old systemtap
versions as this used to be a problem, but looks fine to me too :-)

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
dan...@veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 1/2] snapshot: sort snapshot-list --tree

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 04:35:28PM -0600, Eric Blake wrote:
 Otherwise, the results are not repeatable.
 
 * tools/virsh.c (cmdSnapshotList): Print tree in predictable order.
 ---
  tools/virsh.c |4 ++--
  1 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index 9532bc3..20b3dc5 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -13209,6 +13209,8 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (actual  0)
  goto cleanup;
 
 +qsort(names[0], actual, sizeof(char*), namesorter);
 +
  if (tree) {
  char indentBuf[INDENT_BUFLEN];
  char **parents = vshMalloc(ctl, sizeof(char *) * actual);
 @@ -13245,8 +13247,6 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  ret = true;
  goto cleanup;
  } else {
 -qsort(names[0], actual, sizeof(char*), namesorter);
 -
  for (i = 0; i  actual; i++) {
  /* free up memory from previous iterations of the loop */
  VIR_FREE(parent);

  ACK,

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
dan...@veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 2/2] snapshot: avoid accidental renames with snapshot-edit

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 04:35:29PM -0600, Eric Blake wrote:
 I was a bit surprised that 'virsh snapshot-edit dom name' silently
 allowed me to clone things, while still telling me the old name,
 especially since other commands like 'virsh edit dom' reject rename
 attempts (*).  This fixes things to be more explicit.
 
 (*) Technically, 'virsh edit dom' relies on virDomainDefineXML
 behavior, which rejects attempts to mix a new name with existing
 uuid or new uuid with existing name, but you can create a new
 domain by changing both uuid and name.  On the other hand, while
 snapshot-edit --clone is a true clone, creating a new domain
 would also have to decide whether to clone snapshot metadata,
 managed save, and any other secondary data related to the domain.
 Domain renames are not trivial either.
 
 * tools/virsh.c (cmdSnapshotEdit): Add --rename, --clone.
 * tools/virsh.pod (snapshot-edit): Document them.
 ---
  tools/virsh.c   |   45 -
  tools/virsh.pod |6 ++
  2 files changed, 46 insertions(+), 5 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index 20b3dc5..7151694 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -12830,6 +12830,8 @@ static const vshCmdOptDef opts_snapshot_edit[] = {
  {domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)},
  {snapshotname, VSH_OT_DATA, VSH_OFLAG_REQ, N_(snapshot name)},
  {current, VSH_OT_BOOL, 0, N_(also set edited snapshot as current)},
 +{rename, VSH_OT_BOOL, 0, N_(allow renaming an existing snapshot)},
 +{clone, VSH_OT_BOOL, 0, N_(allow cloning to new name)},
  {NULL, 0, 0, NULL}
  };
 
 @@ -12838,13 +12840,23 @@ cmdSnapshotEdit(vshControl *ctl, const vshCmd *cmd)
  {
  virDomainPtr dom = NULL;
  virDomainSnapshotPtr snapshot = NULL;
 +virDomainSnapshotPtr edited = NULL;
  const char *name;
 +const char *edited_name;
  bool ret = false;
  char *tmp = NULL;
  char *doc = NULL;
  char *doc_edited = NULL;
  unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE;
  unsigned int define_flags = VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
 +bool rename_okay = vshCommandOptBool(cmd, rename);
 +bool clone_okay = vshCommandOptBool(cmd, clone);
 +
 +if (rename_okay  clone_okay) {
 +vshError(ctl, %s,
 + _(--rename and --clone are mutually exclusive));
 +return false;
 +}
 
  if (vshCommandOptBool(cmd, current))
  define_flags |= VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT;
 @@ -12867,8 +12879,6 @@ cmdSnapshotEdit(vshControl *ctl, const vshCmd *cmd)
  doc = virDomainSnapshotGetXMLDesc(snapshot, getxml_flags);
  if (!doc)
  goto cleanup;
 -virDomainSnapshotFree(snapshot);
 -snapshot = NULL;
 
  /* strstr is safe here, since xml came from libvirt API and not user */
  if (strstr(doc, statedisk-snapshot/state))
 @@ -12899,13 +12909,36 @@ cmdSnapshotEdit(vshControl *ctl, const vshCmd *cmd)
  }
 
  /* Everything checks out, so redefine the xml.  */
 -snapshot = virDomainSnapshotCreateXML(dom, doc_edited, define_flags);
 -if (!snapshot) {
 +edited = virDomainSnapshotCreateXML(dom, doc_edited, define_flags);
 +if (!edited) {
  vshError(ctl, _(Failed to update %s), name);
  goto cleanup;
  }
 
 -vshPrint(ctl, _(Snapshot %s edited.\n), name);
 +edited_name = virDomainSnapshotGetName(edited);
 +if (STREQ(name, edited_name)) {
 +vshPrint(ctl, _(Snapshot %s edited.\n), name);
 +} else if (clone_okay) {
 +vshPrint(ctl, _(Snapshot %s cloned to %s.\n), name,
 + edited_name);
 +} else {
 +unsigned int delete_flags;
 +
 +delete_flags = VIR_DOMAIN_SNAPSHOT_DELETE_METADATA_ONLY;
 +if (virDomainSnapshotDelete(rename_okay ? snapshot : edited,
 +delete_flags)  0) {
 +virshReportError(ctl);
 +vshError(ctl, _(Failed to clean up %s),
 + rename_okay ? name : edited_name);
 +goto cleanup;
 +}
 +if (!rename_okay) {
 +vshError(ctl, _(Must use --rename or --clone to change %s to 
 %s),
 + name, edited_name);
 +goto cleanup;
 +}
 +}
 +
  ret = true;
 
  cleanup:
 @@ -12917,6 +12950,8 @@ cleanup:
  }
  if (snapshot)
  virDomainSnapshotFree(snapshot);
 +if (edited)
 +virDomainSnapshotFree(edited);
  if (dom)
  virDomainFree(dom);
  return ret;
 diff --git a/tools/virsh.pod b/tools/virsh.pod
 index 1f7c76f..3351fe0 100644
 --- a/tools/virsh.pod
 +++ b/tools/virsh.pod
 @@ -1952,6 +1952,7 @@ With Isnapshotname, this is a request to make the 
 existing named
  snapshot become the current snapshot, without reverting the domain.
 
  =item Bsnapshot-edit Idomain Isnapshotname [I--current]
 +{[I--rename] | [I--clone]}
 
  Edit the XML configuration file for Isnapshotname of 

Re: [libvirt] [PATCH 0/4] snapshot: optimize qemu relationship traversal

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 06:05:53PM -0600, Eric Blake wrote:
 After working with ESX and VBox, I realized that a tweak to how
 snapshot relationships are stored would speed things up from O(n^2)
 to O(n).  The hash table must be kept for name lookup, but the

  So we went from 0(n^3) to O(n), sounds good :-)

 speedup comes by tracking relationships with each snapshot rather
 than crawling the entire hash table rebuilding those relations
 for every operation that needs particular relations.

  As long as we are sure there is no risk of stale relationship
metadata, this sounds proper ...

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
dan...@veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH 1/4] snapshot: framework for more efficient relation traversal

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 06:05:54PM -0600, Eric Blake wrote:
 No one was using virDomainSnapshotHasChildren, but that was an
 O(n) function.  Exposing and tracking a bit more metadata for each
 snapshot will allow the same query to be made with an O(1) query
 of the member field.  For single snapshot operations (create,
 delete), callers can be trusted to maintain the metadata themselves,
 but for reloading, we can't compute parents as we go since there
 is no guarantee which order things are visited in, so we also
 provide a function to refresh the relationships, and which can
 be used to detect if the user has ignored our warnings and been
 directly modifying files in /var/lib/libvirt/qemu/snapshot.  This
 patch only adds metadata; later patches will actually use it.
 
 This layout intentionally hardcodes the size of each snapshot,
 by tracking sibling pointers, rather than having to deal with
 the headache of yet more memory management by directly sticking
 a child[] on each parent.

Okay, so you're using a 'first child'. But why try to maintain
'nchildren' since you can't get the list in 0(1) anyway and
need to walk the sibling. It's just redundant data to me, but maybe
I didn't understood the use :-)

 * src/conf/domain_conf.h (_virDomainSnapshotObj)
 (_virDomainSnapshotObjList): Add members.
 (virDomainSnapshotUpdateRelations, virDomainSnapshotDropParent):
 New prototypes.
 (virDomainSnapshotHasChildren): Delete.
 * src/conf/domain_conf.c (virDomainSnapshotSetRelations)
 (virDomainSnapshotUpdateRelations, virDomainSnapshotDropParent):
 New functions.
 (virDomainSnapshotHasChildren): Drop unused function.
 * src/libvirt_private.syms (domain_conf): Update exports.
 ---
  src/conf/domain_conf.c   |  108 
 +++---
  src/conf/domain_conf.h   |   13 +-
  src/libvirt_private.syms |3 +-
  3 files changed, 114 insertions(+), 10 deletions(-)
 
 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
 index b9ddf26..d4e127d 100644
 --- a/src/conf/domain_conf.c
 +++ b/src/conf/domain_conf.c
 @@ -12312,13 +12312,6 @@ 
 virDomainSnapshotForEachChild(virDomainSnapshotObjListPtr snapshots,
 
  return act.number;
  }
 -
 -int virDomainSnapshotHasChildren(virDomainSnapshotObjPtr snap,
 - virDomainSnapshotObjListPtr snapshots)
 -{
 -return virDomainSnapshotForEachChild(snapshots, snap, NULL, NULL);
 -}
 -
  typedef enum {
  MARK_NONE,   /* No relation determined yet */
  MARK_DESCENDANT, /* Descendant of target */
 @@ -12423,6 +12416,107 @@ 
 virDomainSnapshotForEachDescendant(virDomainSnapshotObjListPtr snapshots,
  return act.number;
  }
 
 +
 +struct snapshot_set_relation {
 +virDomainSnapshotObjListPtr snapshots;
 +int err;
 +};
 +

 The following function isn't trivial, worth adding a comment about
expected use.

 +static void
 +virDomainSnapshotSetRelations(void *payload,
 +  const void *name ATTRIBUTE_UNUSED,
 +  void *data)
 +{
 +virDomainSnapshotObjPtr obj = payload;
 +struct snapshot_set_relation *curr = data;
 +virDomainSnapshotObjPtr tmp;
 +
 +if (obj-def-parent) {
 +obj-parent = virDomainSnapshotFindByName(curr-snapshots,
 +  obj-def-parent);
 +if (!obj-parent) {
 +curr-err = -1;
 +VIR_WARN(snapshot %s lacks parent, obj-def-name);
 +} else {
 +tmp = obj-parent;
 +while (tmp) {
 +if (tmp == obj) {
 +curr-err = -1;
 +obj-parent = NULL;
 +VIR_WARN(snapshot %s in circular chain, 
 obj-def-name);
 +break;
 +}
 +tmp = tmp-parent;
 +}
 +if (!tmp) {
 +obj-parent-nchildren++;
 +obj-sibling = obj-parent-first_child;
 +obj-parent-first_child = obj;
 +}
 +}
 +} else {
 +curr-snapshots-nroots++;
 +obj-sibling = curr-snapshots-first_root;
 +curr-snapshots-first_root = obj;
 +}
 +}
 +
 +/* Populate parent link and child count of all snapshots, with all
 + * relations starting as 0/NULL.  Return 0 on success, -1 if a parent
 + * is missing or if a circular relationship was requested.  */
 +int
 +virDomainSnapshotUpdateRelations(virDomainSnapshotObjListPtr snapshots)
 +{
 +struct snapshot_set_relation act = { snapshots, 0 };
 +
 +virHashForEach(snapshots-objs, virDomainSnapshotSetRelations, act);
 +return act.err;
 +}
 +
 +/* Prepare to reparent or delete snapshot, by removing it from its
 + * current listed parent.  Note that when bulk removing all children
 + * of a parent, it is faster to just 0 the count rather than calling
 + * this function on each child.  */
 +void
 +virDomainSnapshotDropParent(virDomainSnapshotObjListPtr snapshots,
 + 

Re: [libvirt] [PATCH 2/4] snapshot: track qemu snapshot relations

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 06:05:55PM -0600, Eric Blake wrote:
 Maintain the parent/child relationships of all qemu snapshots.
 
 * src/qemu/qemu_driver.c (qemuDomainSnapshotLoad): Populate
 relationships after loading.
 (qemuDomainSnapshotCreateXML): Set relations on creation; tweak
 redefinition to reuse existing object.
 (qemuDomainSnapshotReparentChildren, qemuDomainSnapshotDelete):
 Clear relations on delete.
 ---
  src/qemu/qemu_driver.c |   72 ++-
  1 files changed, 58 insertions(+), 14 deletions(-)
 
 diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
 index 5db67b8..501a3fc 100644
 --- a/src/qemu/qemu_driver.c
 +++ b/src/qemu/qemu_driver.c
 @@ -376,6 +376,10 @@ static void qemuDomainSnapshotLoad(void *payload,
  vm-current_snapshot = NULL;
  }
 
 +if (virDomainSnapshotUpdateRelations(vm-snapshots)  0)
 +VIR_ERROR(_(Snapshots have inconsistent relations for domain %s),
 +  vm-def-name);
 +

 Hum, so we error out but continue with possibly inconsistent metadata,
isn't that risky ? What would be the cost or failing the load here and
consequences of lack of metadata ?

  /* FIXME: qemu keeps internal track of snapshots.  We can get access
   * to this info via the info snapshots monitor command for running
   * domains, or via qemu-img snapshot -l for shutoff domains.  It would
 @@ -9148,6 +9152,7 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
  virDomainSnapshotDefPtr def = NULL;
  bool update_current = true;
  unsigned int parse_flags = 0;
 +virDomainSnapshotObjPtr other = NULL;
 
  virCheckFlags(VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT |
 @@ -9190,8 +9195,6 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
  goto cleanup;
 
  if (flags  VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE) {
 -virDomainSnapshotObjPtr other = NULL;
 -
  /* Prevent circular chains */
  if (def-parent) {
  if (STREQ(def-name, def-parent)) {
 @@ -9267,7 +9270,12 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
  update_current = true;
  vm-current_snapshot = NULL;
  }
 -virDomainSnapshotObjListRemove(vm-snapshots, other);
 +/* Drop and rebuild the parent relationship, but keep all
 + * child relations by reusing snap.  */
 +virDomainSnapshotDropParent(vm-snapshots, other);
 +virDomainSnapshotDefFree(other-def);
 +other-def = NULL;
 +snap = other;
  }
  if (def-state == VIR_DOMAIN_DISK_SNAPSHOT  def-dom) {
  if (virDomainSnapshotAlignDisks(def,
 @@ -9309,7 +9317,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
  }
  }
 
 -if (!(snap = virDomainSnapshotAssignDef(vm-snapshots, def)))
 +if (snap)
 +snap-def = def;
 +else if (!(snap = virDomainSnapshotAssignDef(vm-snapshots, def)))
  goto cleanup;
  def = NULL;
 
 @@ -9366,11 +9376,25 @@ cleanup:
  if (vm) {
  if (snapshot  !(flags  VIR_DOMAIN_SNAPSHOT_CREATE_NO_METADATA)) {
  if (qemuDomainSnapshotWriteMetadata(vm, snap,
 -driver-snapshotDir)  0)
 +driver-snapshotDir)  0) {
  VIR_WARN(unable to save metadata for snapshot %s,
   snap-def-name);
 -else if (update_current)
 -vm-current_snapshot = snap;
 +} else {
 +if (update_current)
 +vm-current_snapshot = snap;
 +if (snap-def-parent) {
 +other = virDomainSnapshotFindByName(vm-snapshots,
 +snap-def-parent);
 +snap-parent = other;
 +other-nchildren++;
 +snap-sibling = other-first_child;
 +other-first_child = snap;
 +} else {
 +vm-snapshots.nroots++;
 +snap-sibling = vm-snapshots.first_root;
 +vm-snapshots.first_root = snap;
 +}
 +}
  } else if (snap) {
  virDomainSnapshotObjListRemove(vm-snapshots, snap);
  }
 @@ -10062,9 +10086,10 @@ cleanup:
 
  struct snap_reparent {
  struct qemud_driver *driver;
 -const char *parent;
 +virDomainSnapshotObjPtr parent;
  virDomainObjPtr vm;
  int err;
 +virDomainSnapshotObjPtr last;
  };
 
  static void
 @@ -10080,9 +10105,10 @@ qemuDomainSnapshotReparentChildren(void *payload,
  }
 
  VIR_FREE(snap-def-parent);
 +snap-parent = rep-parent;
 
 -if (rep-parent != NULL) {
 -snap-def-parent = strdup(rep-parent);
 +if (rep-parent) {
 +snap-def-parent = strdup(rep-parent-def-name);
 
 

Re: [libvirt] [PATCH 3/4] snapshot: take advantage of new relations

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 06:05:56PM -0600, Eric Blake wrote:
 Among other improvements, virDomainSnapshotForEachDescendant is
 changed from iterative O(n^2) to recursive O(n).  A bit better
 than the O(n^3) implementation in virsh snapshot-list!
 
 * src/conf/domain_conf.c (virDomainSnapshotObjListNum)
 (virDomainSnapshotObjListNumFrom)
 (virDomainSnapshotObjeListGetNames, virDomainSnapshotForEachChild)
 (virDomainSnapshotForEachDescendant): Optimize.
 (virDomainSnapshotActOnDescendant): Tweak.
 (virDomainSnapshotActOnChild, virDomainSnapshotMarkDescendant):
 Delete, now that they are unused.
 ---
  src/conf/domain_conf.c |  148 
 ++--
  1 files changed, 43 insertions(+), 105 deletions(-)
 
 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
 index d4e127d..e77257a 100644
 --- a/src/conf/domain_conf.c
 +++ b/src/conf/domain_conf.c
 @@ -12163,10 +12163,21 @@ int 
 virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
   char **const names, int maxnames,
   unsigned int flags)
  {
 -struct virDomainSnapshotNameData data = { 0, 0, maxnames, names, flags };
 +struct virDomainSnapshotNameData data = { 0, 0, maxnames, names, 0 };
  int i;
 
 -virHashForEach(snapshots-objs, virDomainSnapshotObjListCopyNames, 
 data);
 +data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
 +
 +if (!(flags  VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
 +virHashForEach(snapshots-objs, virDomainSnapshotObjListCopyNames,
 +   data);
 +} else {
 +virDomainSnapshotObjPtr root = snapshots-first_root;
 +while (root) {
 +virDomainSnapshotObjListCopyNames(root, root-def-name, data);
 +root = root-sibling;
 +}
 +}
  if (data.oom) {
  virReportOOMError();
  goto cleanup;
 @@ -12231,9 +12242,21 @@ static void virDomainSnapshotObjListCount(void 
 *payload,
  int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
  unsigned int flags)
  {
 -struct virDomainSnapshotNumData data = { 0, flags };
 +struct virDomainSnapshotNumData data = { 0, 0 };
 
 -virHashForEach(snapshots-objs, virDomainSnapshotObjListCount, data);
 +data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
 +
 +if (!(flags  VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
 +virHashForEach(snapshots-objs, virDomainSnapshotObjListCount, 
 data);
 +} else if (data.flags) {
 +virDomainSnapshotObjPtr root = snapshots-first_root;
 +while (root) {
 +virDomainSnapshotObjListCount(root, root-def-name, data);
 +root = root-sibling;
 +}

  I was just wondering if a data structure with a meta-root snapshot
and unifying first_root as a first_children on that meta-root wouldn't
lead to simpler code overall.

 +} else {
 +data.count = snapshots-nroots;
 +}
 
  return data.count;
  }
 @@ -12251,9 +12274,11 @@ 
 virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
  virDomainSnapshotForEachDescendant(snapshots, snapshot,
 virDomainSnapshotObjListCount,
 data);
 -else
 +else if (data.flags)
  virDomainSnapshotForEachChild(snapshots, snapshot,
virDomainSnapshotObjListCount, data);
 +else
 +data.count = snapshot-nchildren;
 
  return data.count;
  }
 @@ -12271,97 +12296,23 @@ void 
 virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,
  virHashRemoveEntry(snapshots-objs, snapshot-def-name);
  }
 
 -struct snapshot_act_on_child {
 -char *parent;
 -int number;
 -virHashIterator iter;
 -void *data;
 -};
 -
 -static void
 -virDomainSnapshotActOnChild(void *payload,
 -const void *name,
 -void *data)
 -{
 -virDomainSnapshotObjPtr obj = payload;
 -struct snapshot_act_on_child *curr = data;
 -
 -if (obj-def-parent  STREQ(curr-parent, obj-def-parent)) {
 -curr-number++;
 -if (curr-iter)
 -(curr-iter)(payload, name, curr-data);
 -}
 -}
 -
  /* Run iter(data) on all direct children of snapshot, while ignoring all
   * other entries in snapshots.  Return the number of children
   * visited.  No particular ordering is guaranteed.  */
  int
 -virDomainSnapshotForEachChild(virDomainSnapshotObjListPtr snapshots,
 +virDomainSnapshotForEachChild(virDomainSnapshotObjListPtr snapshots 
 ATTRIBUTE_UNUSED,
virDomainSnapshotObjPtr snapshot,
virHashIterator iter,
void *data)
  {
 -struct snapshot_act_on_child act;
 +virDomainSnapshotObjPtr child = snapshot-first_child;
 
 -act.parent = snapshot-def-name;
 -act.number 

Re: [libvirt] [PATCH 4/4] snapshot: drop dead parameters

2011-10-09 Thread Daniel Veillard
On Fri, Oct 07, 2011 at 06:05:57PM -0600, Eric Blake wrote:
 The previous optimizations lead to some follow-on cleanups.
 
 * src/conf/domain_conf.c (virDomainSnapshotForEachChild)
 (virDomainSnapshotForEachDescendant): Drop dead parameter.
 (virDomainSnapshotActOnDescendant)
 (virDomainSnapshotObjListNumFrom)
 (virDomainSnapshotObjListGetNamesFrom): Update callers.
 * src/qemu/qemu_driver.c (qemuDomainSnapshotNumChildren)
 (qemuDomainSnapshotListChildrenNames, qemuDomainSnapshotDelete):
 Likewise.
 * src/conf/domain_conf.h: Update prototypes.
 ---
  src/conf/domain_conf.c |   20 
  src/conf/domain_conf.h |   11 ++-
  src/qemu/qemu_driver.c |   12 +---
  3 files changed, 15 insertions(+), 28 deletions(-)
 
 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
 index e77257a..d52a79f 100644
 --- a/src/conf/domain_conf.c
 +++ b/src/conf/domain_conf.c
 @@ -12192,7 +12192,6 @@ cleanup:
  }
 
  int virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
 - virDomainSnapshotObjListPtr 
 snapshots,
   char **const names, int maxnames,
   unsigned int flags)
  {
 @@ -12202,11 +12201,11 @@ int 
 virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
  data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 
  if (flags  VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
 -virDomainSnapshotForEachDescendant(snapshots, snapshot,
 +virDomainSnapshotForEachDescendant(snapshot,
 virDomainSnapshotObjListCopyNames,
 data);
  else
 -virDomainSnapshotForEachChild(snapshots, snapshot,
 +virDomainSnapshotForEachChild(snapshot,
virDomainSnapshotObjListCopyNames, 
 data);
 
  if (data.oom) {
 @@ -12263,7 +12262,6 @@ int 
 virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
 
  int
  virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
 -virDomainSnapshotObjListPtr snapshots,
  unsigned int flags)
  {
  struct virDomainSnapshotNumData data = { 0, 0 };
 @@ -12271,11 +12269,11 @@ 
 virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
  data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 
  if (flags  VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
 -virDomainSnapshotForEachDescendant(snapshots, snapshot,
 +virDomainSnapshotForEachDescendant(snapshot,
 virDomainSnapshotObjListCount,
 data);
  else if (data.flags)
 -virDomainSnapshotForEachChild(snapshots, snapshot,
 +virDomainSnapshotForEachChild(snapshot,
virDomainSnapshotObjListCount, data);
  else
  data.count = snapshot-nchildren;
 @@ -12300,8 +12298,7 @@ void 
 virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,
   * other entries in snapshots.  Return the number of children
   * visited.  No particular ordering is guaranteed.  */
  int
 -virDomainSnapshotForEachChild(virDomainSnapshotObjListPtr snapshots 
 ATTRIBUTE_UNUSED,
 -  virDomainSnapshotObjPtr snapshot,
 +virDomainSnapshotForEachChild(virDomainSnapshotObjPtr snapshot,
virHashIterator iter,
void *data)
  {
 @@ -12331,15 +12328,14 @@ virDomainSnapshotActOnDescendant(void *payload,
 
  curr-number++;
  (curr-iter)(payload, name, curr-data);
 -virDomainSnapshotForEachDescendant(NULL, obj, curr-iter, curr-data);
 +virDomainSnapshotForEachDescendant(obj, curr-iter, curr-data);
  }
 
  /* Run iter(data) on all descendants of snapshot, while ignoring all
   * other entries in snapshots.  Return the number of descendants
   * visited.  No particular ordering is guaranteed.  */
  int
 -virDomainSnapshotForEachDescendant(virDomainSnapshotObjListPtr snapshots 
 ATTRIBUTE_UNUSED,
 -   virDomainSnapshotObjPtr snapshot,
 +virDomainSnapshotForEachDescendant(virDomainSnapshotObjPtr snapshot,
 virHashIterator iter,
 void *data)
  {
 @@ -12348,7 +12344,7 @@ 
 virDomainSnapshotForEachDescendant(virDomainSnapshotObjListPtr snapshots 
 ATTRIBU
  act.number = 0;
  act.iter = iter;
  act.data = data;
 -virDomainSnapshotForEachChild(NULL, snapshot,
 +virDomainSnapshotForEachChild(snapshot,
virDomainSnapshotActOnDescendant, act);
 
  return act.number;
 diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
 index 9b3870a..ce93215 100644
 --- a/src/conf/domain_conf.h
 +++ b/src/conf/domain_conf.h
 @@ -1464,9 

Re: [libvirt] [PATCH 14/7] snapshot: virsh shorthand for operating on current snap

2011-10-09 Thread Daniel Veillard
On Thu, Oct 06, 2011 at 05:41:11PM -0600, Eric Blake wrote:
 Rather than having to do:
 
 $ virsh snapshot-revert dom $(virsh snapshot-current dom --name)
 
 I thought it would be nice to do:
 
 $ virsh snaphot-revert dom --current
 
 I intentionally made it so that omitting both --current and a name
 is an error (having the absence of a name imply --current seems
 just a bit too magic, so --current must be explicit).
 
 I didn't add 'virsh snapshot-dumpxml --current' since we already
 have 'virsh snapshot-current' for the same task.  All other
 snapshot-* options that take a snapshotname now take --current in
 its place; while keeping snapshot-edit backwards-compatible.
 
 * tools/virsh.c (vshLookupSnapshot): New helper function.
 (cmdSnapshotEdit, cmdSnapshotList, cmdSnapshotParent)
 (cmdSnapshotDelete, cmdDomainSnapshotRevert): Use it, adding an
 option where needed.
 * tools/virsh.pod (snapshot-delete, snapshot-edit)
 (snapshot-list, snapshot-parent, snapshot-revert): Document
 use of --current.
 (snapshot-dumpxml): Mention alternative.
 ---
 
 Does not strictly depend on virDomainSnapshotNumChildren, other
 than the fact that I'm touching 'virsh snapshot-list dom --from name'
 to add 'virsh snapshot-list dom --current'; I could split that
 change out from the rest of the patch if desired to get the ease-of-use
 in the other snapshot-* commands before the new API is approved.
 
  tools/virsh.c   |  109 
 ---
  tools/virsh.pod |   31 ++--
  2 files changed, 90 insertions(+), 50 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index 86b230d..ea7b56b 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -12816,6 +12816,48 @@ cleanup:
  return ret;
  }
 
 +/* Helper for resolving {--current | --ARG name} into a snapshot
 + * belonging to DOM.  If EXCLUSIVE, fail if both --current and arg are
 + * present.  On success, populate *SNAP, and if NAME is not NULL,
 + * *NAME, before returning 0.  On failure, return -1 after issuing an
 + * error message.  */
 +static int
 +vshLookupSnapshot(vshControl *ctl, const vshCmd *cmd,
 +  const char *arg, bool exclusive, virDomainPtr dom,
 +  virDomainSnapshotPtr *snap, const char **name)
 +{
 +bool current = vshCommandOptBool(cmd, current);
 +const char *snapname = NULL;
 +
 +if (vshCommandOptString(cmd, arg, snapname)  0) {
 +vshError(ctl, _(invalid argument for --%s), arg);
 +return -1;
 +}
 +
 +if (exclusive  current  snapname) {
 +vshError(ctl, _(--%s and --current are mutually exclusive), arg);
 +return -1;
 +}
 +
 +if (snapname) {
 +*snap = virDomainSnapshotLookupByName(dom, snapname, 0);
 +} else if (current) {
 +*snap = virDomainSnapshotCurrent(dom, 0);
 +} else {
 +vshError(ctl, _(--%s or --current is required), arg);
 +return -1;
 +}
 +if (!*snap) {
 +virshReportError(ctl);
 +return -1;
 +}
 +
 +if (name  *snap)
 +*name = vshStrdup(ctl, virDomainSnapshotGetName(*snap));
 +
 +return 0;
 +}
 +
  /*
   * snapshot-edit command
   */
 @@ -12827,7 +12869,7 @@ static const vshCmdInfo info_snapshot_edit[] = {
 
  static const vshCmdOptDef opts_snapshot_edit[] = {
  {domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)},
 -{snapshotname, VSH_OT_DATA, VSH_OFLAG_REQ, N_(snapshot name)},
 +{snapshotname, VSH_OT_DATA, 0, N_(snapshot name)},
  {current, VSH_OT_BOOL, 0, N_(also set edited snapshot as current)},
  {NULL, 0, 0, NULL}
  };
 @@ -12845,21 +12887,19 @@ cmdSnapshotEdit(vshControl *ctl, const vshCmd *cmd)
  unsigned int getxml_flags = VIR_DOMAIN_XML_SECURE;
  unsigned int define_flags = VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE;
 
 -if (vshCommandOptBool(cmd, current))
 +if (vshCommandOptBool(cmd, current) 
 +vshCommandOptBool(cmd, snapshotname))
  define_flags |= VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT;
 
  if (!vshConnectionUsability(ctl, ctl-conn))
  return false;
 
 -if (vshCommandOptString(cmd, snapshotname, name) = 0)
 -goto cleanup;
 -
  dom = vshCommandOptDomain(ctl, cmd, NULL);
  if (dom == NULL)
  goto cleanup;
 
 -snapshot = virDomainSnapshotLookupByName(dom, name, 0);
 -if (snapshot == NULL)
 +if (vshLookupSnapshot(ctl, cmd, snapshotname, false, dom,
 +  snapshot, name)  0)
  goto cleanup;
 
  /* Get the XML configuration of the snapshot.  */
 @@ -13109,6 +13149,8 @@ static const vshCmdOptDef opts_snapshot_list[] = {
   N_(list only snapshots that have metadata that would prevent 
 undefine)},
  {tree, VSH_OT_BOOL, 0, N_(list snapshots in a tree)},
  {from, VSH_OT_DATA, 0, N_(limit list to children of given snapshot)},
 +{current, VSH_OT_BOOL, 0,
 + N_(limit list to children of current snapshot)},
  {descendants, VSH_OT_BOOL, 0, N_(with 

Re: [libvirt] [PATCHv2 1/7] snapshot: new virDomainSnapshotListChildrenNames API

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:23PM -0600, Eric Blake wrote:
 The previous API addition allowed traversal up the hierarchy;
 this one makes it easier to traverse down the hierarchy.
 
 In the python bindings, virDomainSnapshotNumChildren can be
 generated, but virDomainSnapshotListChildrenNames had to copy
 from the hand-written example of virDomainSnapshotListNames.
 
 * include/libvirt/libvirt.h.in (virDomainSnapshotNumChildren)
 (virDomainSnapshotListChildrenNames): New prototypes.
 (VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS): New flag alias.
 * src/libvirt.c (virDomainSnapshotNumChildren)
 (virDomainSnapshotListChildrenNames): New functions.
 * src/libvirt_public.syms: Export them.
 * src/driver.h (virDrvDomainSnapshotNumChildren)
 (virDrvDomainSnapshotListChildrenNames): New callbacks.
 * python/generator.py (skip_impl, nameFixup): Update lists.
 * python/libvirt-override-api.xml: Likewise.
 * python/libvirt-override.c
 (libvirt_virDomainSnapshotListChildrenNames): New wrapper function.
 ---
 
 v2: no change
 
  include/libvirt/libvirt.h.in|   27 +++--
  python/generator.py |4 ++
  python/libvirt-override-api.xml |   12 +++-
  python/libvirt-override.c   |   45 
  src/driver.h|   12 
  src/libvirt.c   |  111 
 +++
  src/libvirt_public.syms |2 +
  7 files changed, 204 insertions(+), 9 deletions(-)
 
 diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
 index a832b65..7403a9a 100644
 --- a/include/libvirt/libvirt.h.in
 +++ b/include/libvirt/libvirt.h.in
 @@ -2686,13 +2686,19 @@ virDomainSnapshotPtr 
 virDomainSnapshotCreateXML(virDomainPtr domain,
  char *virDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot,
unsigned int flags);
 
 -/* Flags valid for both virDomainSnapshotNum() and
 - * virDomainSnapshotListNames().  */
 +/* Flags valid for virDomainSnapshotNum(),
 + * virDomainSnapshotListNames(), virDomainSnapshotNumChildren(), and
 + * virDomainSnapshotListChildrenNames().  Note that the interpretation
 + * of flag (10) depends on which function it is passed to.  */
  typedef enum {
 -VIR_DOMAIN_SNAPSHOT_LIST_ROOTS= (1  0), /* Filter by snapshots 
 which
 - have no parents */
 -VIR_DOMAIN_SNAPSHOT_LIST_METADATA = (1  1), /* Filter by snapshots 
 which
 - have metadata */
 +VIR_DOMAIN_SNAPSHOT_LIST_ROOTS   = (1  0), /* Filter by snapshots
 +with no parents, when
 +listing a domain */
 +VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS = (1  0), /* List all descendants,
 +not just children, 
 when
 +listing a snapshot */
 +VIR_DOMAIN_SNAPSHOT_LIST_METADATA= (1  1), /* Filter by snapshots
 +which have metadata 
 */
  } virDomainSnapshotListFlags;

  Hum, okay, a tad bit confusing though

  /* Return the number of snapshots for this domain */
 @@ -2702,6 +2708,15 @@ int virDomainSnapshotNum(virDomainPtr domain, unsigned 
 int flags);
  int virDomainSnapshotListNames(virDomainPtr domain, char **names, int 
 nameslen,
 unsigned int flags);
 
 +/* Return the number of child snapshots for this snapshot */
 +int virDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot,
 + unsigned int flags);
 +
 +/* Get the names of all child snapshots for this snapshot */
 +int virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
 +   char **names, int nameslen,
 +   unsigned int flags);
 +
  /* Get a handle to a named snapshot */
  virDomainSnapshotPtr virDomainSnapshotLookupByName(virDomainPtr domain,
 const char *name,

  Okay

 diff --git a/python/generator.py b/python/generator.py
 index 79558dd..71afdb7 100755
 --- a/python/generator.py
 +++ b/python/generator.py
 @@ -352,6 +352,7 @@ skip_impl = (
  'virConnectListDefinedInterfaces',
  'virConnectListNWFilters',
  'virDomainSnapshotListNames',
 +'virDomainSnapshotListChildrenNames',
  'virConnGetLastError',
  'virGetLastError',
  'virDomainGetInfo',
 @@ -963,6 +964,9 @@ def nameFixup(name, classe, type, file):
  elif name[0:26] == virDomainSnapshotListNames:
  func = name[9:]
  func = string.lower(func[0:1]) + func[1:]
 +elif name[0:28] == virDomainSnapshotNumChildren:
 +func = name[17:]
 +func = string.lower(func[0:1]) + func[1:]
  elif name[0:20] == virDomainSnapshotNum:
  func = name[9:]
  func = 

Re: [libvirt] [PATCHv2 2/7] snapshot: virsh snapshot-list and children

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:24PM -0600, Eric Blake wrote:
 Sometimes, we only care about one branch of the snapshot hierarchy.
 Make it easier to list a single branch, by using the new APIs.
 
 Technically, I could emulate these new virsh options on old servers
 by doing a complete dump, then scraping xml to filter out just the
 snapshots that I care about, but I didn't want to do that in this patch.
 
 * tools/virsh.c (cmdSnapshotList): Add --from, --descendants.
 * tools/virsh.pod (snapshot-list): Document them.
 ---
 
 v2: minor rebase cleanups
 
  tools/virsh.c   |   76 
 ---
  tools/virsh.pod |9 ++-
  2 files changed, 69 insertions(+), 16 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index 955b8df..adafe86 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -13102,6 +13102,8 @@ static const vshCmdOptDef opts_snapshot_list[] = {
  {metadata, VSH_OT_BOOL, 0,
   N_(list only snapshots that have metadata that would prevent 
 undefine)},
  {tree, VSH_OT_BOOL, 0, N_(list snapshots in a tree)},
 +{from, VSH_OT_DATA, 0, N_(limit list to children of given snapshot)},
 +{descendants, VSH_OT_BOOL, 0, N_(with --from, list all descendants)},
  {NULL, 0, 0, NULL}
  };
 
 @@ -13128,25 +13130,36 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  char timestr[100];
  struct tm time_info;
  bool tree = vshCommandOptBool(cmd, tree);
 +const char *from = NULL;
 +virDomainSnapshotPtr start = NULL;
 +
 +if (vshCommandOptString(cmd, from, from)  0) {
 +vshError(ctl, _(invalid from argument '%s'), from);
 +goto cleanup;
 +}
 
  if (vshCommandOptBool(cmd, parent)) {
  if (vshCommandOptBool(cmd, roots)) {
  vshError(ctl, %s,
 - _(--parent and --roots are mutually exlusive));
 + _(--parent and --roots are mutually exclusive));
  return false;
  }
  if (tree) {
  vshError(ctl, %s,
 - _(--parent and --tree are mutually exlusive));
 + _(--parent and --tree are mutually exclusive));
  return false;
  }
  parent_filter = 1;
  } else if (vshCommandOptBool(cmd, roots)) {
  if (tree) {
  vshError(ctl, %s,
 - _(--roots and --tree are mutually exlusive));
 + _(--roots and --tree are mutually exclusive));
  return false;
  }
 +if (from) {
 +vshError(ctl, %s,
 + _(--roots and --from are mutually exclusive));
 +}
  flags |= VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
  }
 
 @@ -13161,16 +13174,29 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (dom == NULL)
  goto cleanup;
 
 -numsnaps = virDomainSnapshotNum(dom, flags);
 -
 -/* Fall back to simulation if --roots was unsupported.  */
 -if (numsnaps  0  last_error-code == VIR_ERR_INVALID_ARG 
 -(flags  VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
 -virFreeError(last_error);
 -last_error = NULL;
 -parent_filter = -1;
 -flags = ~VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
 +if (from) {
 +start = virDomainSnapshotLookupByName(dom, from, 0);
 +if (!start)
 +goto cleanup;
 +if (vshCommandOptBool(cmd, descendants) || tree) {
 +flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 +}
 +numsnaps = virDomainSnapshotNumChildren(start, flags);
 +if (numsnaps = 0  tree)
 +numsnaps++;
 +/* XXX Is it worth emulating --from on older servers?  */
 +} else {
  numsnaps = virDomainSnapshotNum(dom, flags);
 +
 +/* Fall back to simulation if --roots was unsupported. */
 +if (numsnaps  0  last_error-code == VIR_ERR_INVALID_ARG 
 +(flags  VIR_DOMAIN_SNAPSHOT_LIST_ROOTS)) {
 +virFreeError(last_error);
 +last_error = NULL;
 +parent_filter = -1;
 +flags = ~VIR_DOMAIN_SNAPSHOT_LIST_ROOTS;
 +numsnaps = virDomainSnapshotNum(dom, flags);
 +}
  }
 
  if (numsnaps  0)
 @@ -13196,14 +13222,32 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (VIR_ALLOC_N(names, numsnaps)  0)
  goto cleanup;
 
 -actual = virDomainSnapshotListNames(dom, names, numsnaps, flags);
 +if (from) {
 +/* When mixing --from and --tree, we want to start the tree at the
 + * given snapshot.  Without --tree, only list the children.  */
 +if (tree) {
 +if (numsnaps)
 +actual = virDomainSnapshotListChildrenNames(start, names + 1,
 +numsnaps - 1,
 +flags);
 +if (actual = 0) {
 +actual++;
 +names[0] = 

Re: [libvirt] [PATCHv2 3/7] snapshot: virsh fallback for snapshot-list --tree --from

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:25PM -0600, Eric Blake wrote:
 Emulating --from requires grabbing the entire list of snapshots
 and their parents, and recursively iterating over the list from
 the point of interest - but we already do that for --tree.  This
 turns on emulation for that situation.
 
 * tools/virsh.c (__vshControl): Rename member.
 (vshReconnect, cmdConnect, vshGetSnapshotParent): Update clients.
 (cmdSnapshotList): Add fallback.
 ---
 
 v2: reuse existing ctl flag, so that virsh in shell mode doesn't
 repeatedly try non-working commands
 
  tools/virsh.c |   43 +--
  1 files changed, 29 insertions(+), 14 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index adafe86..e3bc364 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -246,8 +246,8 @@ typedef struct __vshControl {
  char *historyfile;  /* readline history file name */
  bool useGetInfo;/* must use virDomainGetInfo, since
 virDomainGetState is not supported */
 -bool useSnapshotGetXML; /* must use virDomainSnapshotGetXMLDesc, 
 since
 -   virDomainSnapshotGetParent is missing */
 +bool useSnapshotOld;/* cannot use virDomainSnapshotGetParent or
 +   virDomainSnapshotNumChildren */
  } __vshControl;
 
  typedef struct vshCmdGrp {
 @@ -599,7 +599,7 @@ vshReconnect(vshControl *ctl)
  vshError(ctl, %s, _(Reconnected to the hypervisor));
  disconnected = 0;
  ctl-useGetInfo = false;
 -ctl-useSnapshotGetXML = false;
 +ctl-useSnapshotOld = false;
  }
 
  /* ---
 @@ -747,7 +747,7 @@ cmdConnect(vshControl *ctl, const vshCmd *cmd)
  ctl-name = vshStrdup(ctl, name);
 
  ctl-useGetInfo = false;
 -ctl-useSnapshotGetXML = false;
 +ctl-useSnapshotOld = false;
  ctl-readonly = ro;
 
  ctl-conn = virConnectOpenAuth(ctl-name, virConnectAuthPtrDefault,
 @@ -13042,7 +13042,7 @@ vshGetSnapshotParent(vshControl *ctl, 
 virDomainSnapshotPtr snapshot,
  *parent_name = NULL;
 
  /* Try new API, since it is faster. */
 -if (!ctl-useSnapshotGetXML) {
 +if (!ctl-useSnapshotOld) {
  parent = virDomainSnapshotGetParent(snapshot, 0);
  if (parent) {
  /* API works, and virDomainSnapshotGetName will be accurate */
 @@ -13056,7 +13056,7 @@ vshGetSnapshotParent(vshControl *ctl, 
 virDomainSnapshotPtr snapshot,
  goto cleanup;
  }
  /* API didn't work, fall back to XML scraping. */
 -ctl-useSnapshotGetXML = true;
 +ctl-useSnapshotOld = true;
  }
 
  xml = virDomainSnapshotGetXMLDesc(snapshot, 0);
 @@ -13181,10 +13181,22 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (vshCommandOptBool(cmd, descendants) || tree) {
  flags |= VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
  }
 -numsnaps = virDomainSnapshotNumChildren(start, flags);
 -if (numsnaps = 0  tree)
 -numsnaps++;
 -/* XXX Is it worth emulating --from on older servers?  */
 +numsnaps = ctl-useSnapshotOld ? -1 :
 +virDomainSnapshotNumChildren(start, flags);
 +/* XXX Is it worth emulating --from without --tree on older servers? 
  */
 +if (tree) {
 +if (numsnaps = 0) {
 +numsnaps++;
 +} else if (ctl-useSnapshotOld ||
 +   last_error-code == VIR_ERR_NO_SUPPORT) {
 +/* We can emulate --tree --from.  */
 +virFreeError(last_error);
 +last_error = NULL;
 +ctl-useSnapshotOld = true;
 +flags = ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 +numsnaps = virDomainSnapshotNum(dom, flags);
 +}
 +}
  } else {
  numsnaps = virDomainSnapshotNum(dom, flags);
 
 @@ -13199,8 +13211,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  }
  }
 
 -if (numsnaps  0)
 +if (numsnaps  0) {
 +if (!last_error)
 +vshError(ctl, _(missing support));
  goto cleanup;
 +}
 
  if (!tree) {
  if (parent_filter  0)
 @@ -13222,7 +13237,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (VIR_ALLOC_N(names, numsnaps)  0)
  goto cleanup;
 
 -if (from) {
 +if (from  !ctl-useSnapshotOld) {
  /* When mixing --from and --tree, we want to start the tree at the
   * given snapshot.  Without --tree, only list the children.  */
  if (tree) {
 @@ -13247,7 +13262,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (tree) {
  char indentBuf[INDENT_BUFLEN];
  char **parents = vshCalloc(ctl, sizeof(char *), actual);
 -for (i = (from ? 1 : 0); i  actual; i++) {
 +for (i = (from  !ctl-useSnapshotOld); i  actual; i++) {
  /* free up memory from previous iterations 

Re: [libvirt] [PATCHv2 4/7] snapshot: virsh fallback for snapshot-list --from children

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:26PM -0600, Eric Blake wrote:
 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.
 ---
 
 v2: fix compilation error, rebase around ctl flag
 
  tools/virsh.c |   48 
  1 files changed, 32 insertions(+), 16 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index e3bc364..b2523d3 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -13117,6 +13117,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;
 @@ -13132,6 +13133,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  bool tree = vshCommandOptBool(cmd, tree);
  const char *from = NULL;
  virDomainSnapshotPtr start = NULL;
 +bool descendants = false;
 
  if (vshCommandOptString(cmd, from, from)  0) {
  vshError(ctl, _(invalid from argument '%s'), from);
 @@ -13175,27 +13177,29 @@ 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 = ctl-useSnapshotOld ? -1 :
  virDomainSnapshotNumChildren(start, flags);
 -/* XXX Is it worth emulating --from without --tree on older servers? 
  */
 -if (tree) {
 -if (numsnaps = 0) {
 -numsnaps++;
 -} else if (ctl-useSnapshotOld ||
 -   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) 
 +(ctl-useSnapshotOld ||
 + last_error-code == VIR_ERR_NO_SUPPORT)) {
 +/* We can emulate --from.  */
  virFreeError(last_error);
  last_error = NULL;
  ctl-useSnapshotOld = true;
  flags = ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
  numsnaps = virDomainSnapshotNum(dom, flags);
  }
 +} else if (tree) {
 +numsnaps++;
  }
  } else {
  numsnaps = virDomainSnapshotNum(dom, flags);
 @@ -13259,9 +13263,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 || ctl-useSnapshotOld) {
 +parents = vshCalloc(ctl, sizeof(char *), actual);
  for (i = (from  !ctl-useSnapshotOld); i  actual; i++) {
  /* free up memory from previous iterations of the loop */
  if (snapshot)
 @@ -13275,6 +13281,9 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  goto cleanup;
  }
  }
 +}
 +if (tree) {
 +char indentBuf[INDENT_BUFLEN];
  for (i = 0 ; i  actual ; i++) {
  memset(indentBuf, '\0', sizeof indentBuf);
  if (ctl-useSnapshotOld ? STREQ(names[i], from) : !parents[i])
 @@ -13288,16 +13297,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 (ctl-useSnapshotOld  descendants) {
 +/* XXX emulate --descendants as well */
 +goto cleanup;
 +}
 
  for (i = 0; i  actual; i++) {
 +if (ctl-useSnapshotOld  STRNEQ_NULLABLE(parents[i], from))
 +continue;
 +
  /* free up memory from previous iterations of the loop */
  VIR_FREE(parent);
  VIR_FREE(state);
 @@ -13362,9 +13374,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)
 

Re: [libvirt] [PATCHv2 5/7] snapshot: virsh fallback for snapshot-list --descendants --from

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:27PM -0600, Eric Blake wrote:
 Given a list of snapshots and their parents, finding all descendants
 requires a hairy traversal.  This code is O(n^3); it could maybe be
 made to scale O(n^2) with the use of a hash table, but that costs more
 memory.  Hopefully there aren't too many people with a hierarchy
 so large as to approach REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX (1024).
 
 * tools/virsh.c (cmdSnapshotList): Add final fallback.
 ---
 
 v2: rebase around ctl flag
 
  tools/virsh.c |   67 
 +++--
  1 files changed, 60 insertions(+), 7 deletions(-)
 
 diff --git a/tools/virsh.c b/tools/virsh.c
 index b2523d3..ec6f854 100644
 --- a/tools/virsh.c
 +++ b/tools/virsh.c
 @@ -13133,6 +13133,7 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  bool tree = vshCommandOptBool(cmd, tree);
  const char *from = NULL;
  virDomainSnapshotPtr start = NULL;
 +int start_index = -1;
  bool descendants = false;
 
  if (vshCommandOptString(cmd, from, from)  0) {
 @@ -13187,10 +13188,8 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  numsnaps = ctl-useSnapshotOld ? -1 :
  virDomainSnapshotNumChildren(start, flags);
  if (numsnaps  0) {
 -/* XXX also want to emulate --descendants without --tree */
 -if ((!descendants || tree) 
 -(ctl-useSnapshotOld ||
 - last_error-code == VIR_ERR_NO_SUPPORT)) {
 +if (ctl-useSnapshotOld ||
 +last_error-code == VIR_ERR_NO_SUPPORT) {
  /* We can emulate --from.  */
  virFreeError(last_error);
  last_error = NULL;
 @@ -13269,6 +13268,11 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  if (tree || ctl-useSnapshotOld) {
  parents = vshCalloc(ctl, sizeof(char *), actual);
  for (i = (from  !ctl-useSnapshotOld); i  actual; i++) {
 +if (ctl-useSnapshotOld  STREQ(names[i], from)) {
 +start_index = i;
 +continue;
 +}
 +
  /* free up memory from previous iterations of the loop */
  if (snapshot)
  virDomainSnapshotFree(snapshot);
 @@ -13302,12 +13306,61 @@ cmdSnapshotList(vshControl *ctl, const vshCmd *cmd)
  goto cleanup;
  } else {
  if (ctl-useSnapshotOld  descendants) {
 -/* XXX emulate --descendants as well */
 -goto cleanup;
 +bool changed = false;
 +
 +/* Make multiple passes over the list - first pass NULLs
 + * out all roots except start, remaining passes NULL out
 + * any entry whose parent is not still in list.  Also, we
 + * NULL out parent when name is known to be in list.
 + * Sorry, this is O(n^3) - hope your hierarchy isn't huge.  */
 +if (start_index  0) {
 +vshError(ctl, _(snapshot %s disappeared from list), from);
 +goto cleanup;
 +}
 +for (i = 0; i  actual; i++) {
 +if (i == start_index)
 +continue;
 +if (!parents[i]) {
 +VIR_FREE(names[i]);
 +} else if (STREQ(parents[i], from)) {
 +VIR_FREE(parents[i]);
 +changed = true;
 +}
 +}
 +if (!changed) {
 +ret = true;
 +goto cleanup;
 +}
 +while (changed) {
 +changed = false;
 +for (i = 0; i  actual; i++) {
 +bool found = false;
 +int j;
 +
 +if (!names[i] || !parents[i])
 +continue;
 +for (j = 0; j  actual; j++) {
 +if (!names[j] || i == j)
 +continue;
 +if (STREQ(parents[i], names[j])) {
 +found = true;
 +if (!parents[j])
 +VIR_FREE(parents[i]);
 +break;
 +}
 +}
 +if (!found) {
 +changed = true;
 +VIR_FREE(names[i]);
 +}
 +}
 +}
 +VIR_FREE(names[start_index]);
  }
 
  for (i = 0; i  actual; i++) {
 -if (ctl-useSnapshotOld  STRNEQ_NULLABLE(parents[i], from))
 +if (ctl-useSnapshotOld 
 +(descendants ? !names[i] : STRNEQ_NULLABLE(parents[i], 
 from)))
  continue;
 
  /* free up memory from previous iterations of the loop */

  ACK, to be removed in second patch set anyway :-)

Daniel

-- 
Daniel Veillard  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/

Re: [libvirt] [PATCHv2 6/7] snapshot: remote protocol for snapshot children

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:28PM -0600, Eric Blake wrote:
 Very mechanical.  I'm so glad we've automated the generation of things,
 compared to what it was in 0.8.x days, where this would be much longer.
 
 * src/remote/remote_protocol.x
 (REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN)
 (REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES): New rpcs.
 (remote_domain_snapshot_num_children_args)
 (remote_domain_snapshot_num_children_ret)
 (remote_domain_snapshot_list_children_names_args)
 (remote_domain_snapshot_list_children_names_ret): New structs.
 * src/remote/remote_driver.c (remote_driver): Use it.
 * src/remote_protocol-structs: Update.
 ---
 
 v2: fix typo in remote_protocol-structs
 
  src/remote/remote_driver.c   |2 ++
  src/remote/remote_protocol.x |   25 +++--
  src/remote_protocol-structs  |   20 
  3 files changed, 45 insertions(+), 2 deletions(-)
 
 diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
 index 83f4f3c..0e303df 100644
 --- a/src/remote/remote_driver.c
 +++ b/src/remote/remote_driver.c
 @@ -4411,6 +4411,8 @@ static virDriver remote_driver = {
  .domainSnapshotGetXMLDesc = remoteDomainSnapshotGetXMLDesc, /* 0.8.0 */
  .domainSnapshotNum = remoteDomainSnapshotNum, /* 0.8.0 */
  .domainSnapshotListNames = remoteDomainSnapshotListNames, /* 0.8.0 */
 +.domainSnapshotNumChildren = remoteDomainSnapshotNumChildren, /* 0.9.7 */
 +.domainSnapshotListChildrenNames = 
 remoteDomainSnapshotListChildrenNames, /* 0.9.7 */
  .domainSnapshotLookupByName = remoteDomainSnapshotLookupByName, /* 0.8.0 
 */
  .domainHasCurrentSnapshot = remoteDomainHasCurrentSnapshot, /* 0.8.0 */
  .domainSnapshotGetParent = remoteDomainSnapshotGetParent, /* 0.9.7 */
 diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
 index c8a92fd..f95253e 100644
 --- a/src/remote/remote_protocol.x
 +++ b/src/remote/remote_protocol.x
 @@ -2067,6 +2067,25 @@ struct remote_domain_snapshot_list_names_ret {
  remote_nonnull_string namesREMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX; /* 
 insert@1 */
  };
 
 +struct remote_domain_snapshot_num_children_args {
 +remote_nonnull_domain_snapshot snap;
 +unsigned int flags;
 +};
 +
 +struct remote_domain_snapshot_num_children_ret {
 +int num;
 +};
 +
 +struct remote_domain_snapshot_list_children_names_args {
 +remote_nonnull_domain_snapshot snap;
 +int maxnames;
 +unsigned int flags;
 +};
 +
 +struct remote_domain_snapshot_list_children_names_ret {
 +remote_nonnull_string namesREMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX; /* 
 insert@1 */
 +};
 +
  struct remote_domain_snapshot_lookup_by_name_args {
  remote_nonnull_domain dom;
  remote_nonnull_string name;
 @@ -2524,8 +2543,10 @@ enum remote_procedure {
  REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB = 241, /* skipgen skipgen */
  REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /* autogen autogen */
  REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /* skipgen skipgen */
 -REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen */
 -REMOTE_PROC_DOMAIN_RESET = 245 /* autogen autogen */
 +REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /* autogen autogen 
 priority:high */
 +REMOTE_PROC_DOMAIN_RESET = 245, /* autogen autogen */
 +REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN = 246, /* autogen autogen 
 priority:high */
 +REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES = 247 /* autogen autogen 
 priority:high */
 
  /*
   * Notice how the entries are grouped in sets of 10 ?
 diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
 index 69175cc..7894441 100644
 --- a/src/remote_protocol-structs
 +++ b/src/remote_protocol-structs
 @@ -1557,6 +1557,24 @@ struct remote_domain_snapshot_list_names_ret {
  remote_nonnull_string * names_val;
  } names;
  };
 +struct remote_domain_snapshot_num_children_args {
 +remote_nonnull_domain_snapshot snap;
 +u_int  flags;
 +};
 +struct remote_domain_snapshot_num_children_ret {
 +intnum;
 +};
 +struct remote_domain_snapshot_list_children_names_args {
 +remote_nonnull_domain_snapshot snap;
 +intmaxnames;
 +u_int  flags;
 +};
 +struct remote_domain_snapshot_list_children_names_ret {
 +struct {
 +u_int  names_len;
 +remote_nonnull_string * names_val;
 +} names;
 +};
  struct remote_domain_snapshot_lookup_by_name_args {
  remote_nonnull_domain  dom;
  remote_nonnull_string  name;
 @@ -1971,4 +1989,6 @@ enum remote_procedure {
  REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243,
  REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244,
  REMOTE_PROC_DOMAIN_RESET = 245,
 +REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN = 246,
 +REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES = 247,
  };

  

Re: [libvirt] [PATCHv2 7/7] snapshot: implement snapshot children listing in qemu

2011-10-09 Thread Daniel Veillard
On Fri, Sep 30, 2011 at 05:09:29PM -0600, Eric Blake wrote:
 Not too hard to wire up.  The trickiest part is realizing that
 listing children of a snapshot cannot use SNAPSHOT_LIST_ROOTS,
 and that we overloaded that bit to also mean SNAPSHOT_LIST_DESCENDANTS;
 we use that bit to decide which iteration to use, but don't want
 the existing counting/listing functions to see that bit.
 
 * src/conf/domain_conf.h (virDomainSnapshotObjListNumFrom)
 (virDomainSnapshotObjListGetNamesFrom): New prototypes.
 * src/conf/domain_conf.c (virDomainSnapshotObjListNumFrom)
 (virDomainSnapshotObjListGetNamesFrom): New functions.
 * src/libvirt_private.syms (domain_conf.h): Export them.
 * src/qemu/qemu_driver.c (qemuDomainSnapshotNumChildren)
 (qemuDomainSnapshotListChildrenNames): New functions.
 ---
 
 v2: no change, but now virsh changes have been tested both with
 and without this patch
 
  src/conf/domain_conf.c   |   51 +++
  src/conf/domain_conf.h   |7 
  src/libvirt_private.syms |2 +
  src/qemu/qemu_driver.c   |   87 
 ++
  4 files changed, 147 insertions(+), 0 deletions(-)
 
 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
 index c141982..438e3b6 100644
 --- a/src/conf/domain_conf.c
 +++ b/src/conf/domain_conf.c
 @@ -12138,6 +12138,37 @@ cleanup:
  return -1;
  }
 
 +int virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
 + virDomainSnapshotObjListPtr 
 snapshots,
 + char **const names, int maxnames,
 + unsigned int flags)
 +{
 +struct virDomainSnapshotNameData data = { 0, 0, maxnames, names, 0 };
 +int i;
 +
 +data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 +
 +if (flags  VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
 +virDomainSnapshotForEachDescendant(snapshots, snapshot,
 +   virDomainSnapshotObjListCopyNames,
 +   data);
 +else
 +virDomainSnapshotForEachChild(snapshots, snapshot,
 +  virDomainSnapshotObjListCopyNames, 
 data);
 +
 +if (data.oom) {
 +virReportOOMError();
 +goto cleanup;
 +}
 +
 +return data.numnames;
 +
 +cleanup:
 +for (i = 0; i  data.numnames; i++)
 +VIR_FREE(data.names[i]);
 +return -1;
 +}
 +
  struct virDomainSnapshotNumData {
  int count;
  unsigned int flags;
 @@ -12165,6 +12196,26 @@ int 
 virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
  return data.count;
  }
 
 +int
 +virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
 +virDomainSnapshotObjListPtr snapshots,
 +unsigned int flags)
 +{
 +struct virDomainSnapshotNumData data = { 0, 0 };
 +
 +data.flags = flags  ~VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS;
 +
 +if (flags  VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS)
 +virDomainSnapshotForEachDescendant(snapshots, snapshot,
 +   virDomainSnapshotObjListCount,
 +   data);
 +else
 +virDomainSnapshotForEachChild(snapshots, snapshot,
 +  virDomainSnapshotObjListCount, data);
 +
 +return data.count;
 +}
 +
  virDomainSnapshotObjPtr
  virDomainSnapshotFindByName(const virDomainSnapshotObjListPtr snapshots,
  const char *name)
 diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
 index 0bc0042..1258740 100644
 --- a/src/conf/domain_conf.h
 +++ b/src/conf/domain_conf.h
 @@ -1488,6 +1488,13 @@ int 
 virDomainSnapshotObjListGetNames(virDomainSnapshotObjListPtr snapshots,
   unsigned int flags);
  int virDomainSnapshotObjListNum(virDomainSnapshotObjListPtr snapshots,
  unsigned int flags);
 +int virDomainSnapshotObjListGetNamesFrom(virDomainSnapshotObjPtr snapshot,
 + virDomainSnapshotObjListPtr 
 snapshots,
 + char **const names, int maxnames,
 + unsigned int flags);
 +int virDomainSnapshotObjListNumFrom(virDomainSnapshotObjPtr snapshot,
 +virDomainSnapshotObjListPtr snapshots,
 +unsigned int flags);
  virDomainSnapshotObjPtr virDomainSnapshotFindByName(const 
 virDomainSnapshotObjListPtr snapshots,
  const char *name);
  void virDomainSnapshotObjListRemove(virDomainSnapshotObjListPtr snapshots,
 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
 index c2a3fab..6b9ceaa 100644
 --- a/src/libvirt_private.syms
 +++ b/src/libvirt_private.syms
 @@ -413,7 +413,9 @@ 

[libvirt] [v2] storage: Do not use comma as seperator for lvs output

2011-10-09 Thread Osier Yang
* src/storage/storage_backend_logical.c:

If a logical vol is created as striped. (e.g. --stripes 3),
the device field of lvs output will have multiple fileds which are
seperated by comma. Thus the RE we write in the codes will not
work well anymore. E.g. (lvs output for a stripped vol, uses # as
seperator here):

test_stripes##fSLSZH-zAS2-yAIb-n4mV-Al9u-HA3V-oo9K1B#\
/dev/sdc1(10240),/dev/sdd1(0)#42949672960#4194304

The RE we use:

const char *regexes[] = {
^\\s*(\\S+),(\\S*),(\\S+),(\\S+)\\((\\S+)\\),(\\S+),([0-9]+),?\\s*$
};

Also the RE doesn't match the devices field of striped vol properly,
it contains multiple device path and offset.

This patch mainly does:
1) Change the seperator into #
2) Change the RE for devices field from (\\S+)\\((\\S+)\\)
   into (\\S+).
3) Add two new options for lvs command, (segtype, stripes)
4) Extend the RE to match the value for the two new fields.
5) Parse the devices field seperately in virStorageBackendLogicalMakeVol,
   multiple extents info are generated if the vol is striped. The
   number of extents is equal to the stripes number of the striped vol.

A incidental fix: (virStorageBackendLogicalMakeVol)
Free vol if it's new created and there is error.

Demo on striped vol with the patch applied:

% virsh vol-dumpxml /dev/test_vg/vol_striped2
volume
  namevol_striped2/name
  keyQuWqmn-kIkZ-IATt-67rc-OWEP-1PHX-Cl2ICs/key
  source
device path='/dev/sda5'
  extent start='79691776' end='88080384'/
/device
device path='/dev/sda6'
  extent start='62914560' end='71303168'/
/device
  /source
  capacity8388608/capacity
  allocation8388608/allocation
  target
path/dev/test_vg/vol_striped2/path
permissions
  mode0660/mode
  owner0/owner
  group6/group
  labelsystem_u:object_r:fixed_disk_device_t:s0/label
/permissions
  /target
/volume

RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=727474

v1 - v2:
   v1 just simply changes the seperator into #.

---
 src/storage/storage_backend_logical.c |  156 +
 1 files changed, 121 insertions(+), 35 deletions(-)

diff --git a/src/storage/storage_backend_logical.c 
b/src/storage/storage_backend_logical.c
index 589f486..dda68fd 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -62,13 +62,22 @@ virStorageBackendLogicalSetActive(virStoragePoolObjPtr pool,
 }
 
 
+#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED striped
+
 static int
 virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
 char **const groups,
 void *data)
 {
 virStorageVolDefPtr vol = NULL;
+bool is_new_vol = false;
 unsigned long long offset, size, length;
+const char *regex_unit = (\\S+)\\((\\S+)\\);
+char *regex = NULL;
+regex_t *reg = NULL;
+regmatch_t *vars = NULL;
+char *p = NULL;
+int i, err, nextents, nvars, ret = -1;
 
 /* See if we're only looking for a specific volume */
 if (data != NULL) {
@@ -88,19 +97,18 @@ virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
 return -1;
 }
 
+is_new_vol = true;
 vol-type = VIR_STORAGE_VOL_BLOCK;
 
 if ((vol-name = strdup(groups[0])) == NULL) {
 virReportOOMError();
-virStorageVolDefFree(vol);
-return -1;
+goto cleanup;
 }
 
 if (VIR_REALLOC_N(pool-volumes.objs,
   pool-volumes.count + 1)) {
 virReportOOMError();
-virStorageVolDefFree(vol);
-return -1;
+goto cleanup;
 }
 pool-volumes.objs[pool-volumes.count++] = vol;
 }
@@ -109,8 +117,7 @@ virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
 if (virAsprintf(vol-target.path, %s/%s,
 pool-def-target.path, vol-name)  0) {
 virReportOOMError();
-virStorageVolDefFree(vol);
-return -1;
+goto cleanup;
 }
 }
 
@@ -118,8 +125,7 @@ virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
 if (virAsprintf(vol-backingStore.path, %s/%s,
 pool-def-target.path, groups[1])  0) {
 virReportOOMError();
-virStorageVolDefFree(vol);
-return -1;
+goto cleanup;
 }
 
 vol-backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2;
@@ -128,47 +134,127 @@ virStorageBackendLogicalMakeVol(virStoragePoolObjPtr 
pool,
 if (vol-key == NULL 
 (vol-key = strdup(groups[2])) == NULL) {
 virReportOOMError();
-return -1;
+goto cleanup;
 }
 
 if (virStorageBackendUpdateVolInfo(vol, 1)  0)
-return -1;
+goto cleanup;
 
+nextents = 1;
+if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
+if (virStrToLong_i(groups[5], NULL, 10, nextents)  0) {
+ 

Re: [libvirt] [PATCH] qemu: Do not reattach PCI device used by other domain when shutdown

2011-10-09 Thread Osier Yang
Anybody could help review this? Thanks

Osier
于 2011年09月27日 14:53, Osier Yang 写道:
 When failing on starting a domain, it tries to reattach all the PCI
 devices defined in the domain conf, regardless of whether the devices
 are still used by other domain. This will cause the devices are deleted
 from the list qemu_driver-activePciHostdevs, thus the devices will be
 thought as usable even if it's not true. And following commands
 nodedev-{reattach,reset} will be successful.

 How to reproduce:
   1) Define two domains with same PCI device defined in the confs.
   2) # virsh start domain1
   3) # virsh start domain2
   4) # virsh nodedev-reattach $pci_device

 You will see the device will be reattached to host successfully.
 As pciDeviceReattach just check if the device is still used by
 other domain via checking if the device is in list driver-activePciHostdevs,
 however, the device is deleted from the list by step 2).

 This patch is to prohibit the bug by:
   1) Prohibit a domain starting or device attachment right at
  preparation period (qemuPrepareHostdevPCIDevices) if the
  device is in list driver-activePciHostdevs, which means
  it's used by other domain.

   2) Introduces a new field for struct _pciDevice, (char *used_by),
  it will be set as the domain name at preparation period,
  (qemuPrepareHostdevPCIDevices). Thus we can prohibit deleting
  the device from driver-activePciHostdevs if it's still used by
  other domain when stopping the domain process.

 * src/pci.h (define two internal functions, pciDeviceSetUsedBy and
 pciDevceGetUsedBy)
 * src/pci.c (new field char *used_by for struct _pciDevice,
 implementations for the two new functions)
 * src/libvirt_private.syms (Add the two new internal functions)
 * src/qemu_hostdev.h (Modify the definition of functions
 qemuPrepareHostdevPCIDevices, and qemuDomainReAttachHostdevDevices)
 * src/qemu_hostdev.c (Prohibit preparation and don't delete the
 device from activePciHostdevs list if it's still used by other domain)
 * src/qemu_hotplug.c (Update function usage, as the definitions are
 changed)
 ---
  src/libvirt_private.syms |2 ++
  src/qemu/qemu_hostdev.c  |   31 ---
  src/qemu/qemu_hostdev.h  |2 ++
  src/qemu/qemu_hotplug.c  |4 ++--
  src/util/pci.c   |   22 ++
  src/util/pci.h   |3 +++
  6 files changed, 59 insertions(+), 5 deletions(-)

 diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
 index 8235ea1..a5c5e6c 100644
 --- a/src/libvirt_private.syms
 +++ b/src/libvirt_private.syms
 @@ -872,6 +872,7 @@ virNWFilterHashTableRemoveEntry;
  pciDettachDevice;
  pciDeviceFileIterate;
  pciDeviceGetManaged;
 +pciDeviceGetUsedBy;
  pciDeviceIsAssignable;
  pciDeviceIsVirtualFunction;
  pciDeviceListAdd;
 @@ -884,6 +885,7 @@ pciDeviceListSteal;
  pciDeviceNetName;
  pciDeviceReAttachInit;
  pciDeviceSetManaged;
 +pciDeviceSetUsedBy;
  pciFreeDevice;
  pciGetDevice;
  pciGetPhysicalFunction;
 diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
 index 6f77717..ef9e3b7 100644
 --- a/src/qemu/qemu_hostdev.c
 +++ b/src/qemu/qemu_hostdev.c
 @@ -101,6 +101,7 @@ cleanup:
  
  
  int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
 + const char *name,
   virDomainHostdevDefPtr *hostdevs,
   int nhostdevs)
  {
 @@ -126,7 +127,10 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver 
 *driver,
  for (i = 0; i  pciDeviceListCount(pcidevs); i++) {
  pciDevice *dev = pciDeviceListGet(pcidevs, i);
  if (!pciDeviceIsAssignable(dev, !driver-relaxedACS))
 -goto reattachdevs;
 +goto cleanup;
 +
 +if (pciDeviceListFind(driver-activePciHostdevs, dev))
 +goto cleanup;
  
  if (pciDeviceGetManaged(dev) 
  pciDettachDevice(dev, driver-activePciHostdevs)  0)
 @@ -156,6 +160,14 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver 
 *driver,
  pciDeviceListSteal(pcidevs, dev);
  }
  
 +/* Now set the used_by_domain of the device in driver-activePciHostdevs
 + * as domain name.
 + */
 +for (i = 0; i  pciDeviceListCount(driver-activePciHostdevs); i++) {
 +pciDevice * dev = pciDeviceListGet(driver-activePciHostdevs, i);
 +pciDeviceSetUsedBy(dev, name);
 +}
 +
  ret = 0;
  goto cleanup;
  
 @@ -183,7 +195,7 @@ static int
  qemuPrepareHostPCIDevices(struct qemud_driver *driver,
virDomainDefPtr def)
  {
 -return qemuPrepareHostdevPCIDevices(driver, def-hostdevs, 
 def-nhostdevs);
 +return qemuPrepareHostdevPCIDevices(driver, def-name, def-hostdevs, 
 def-nhostdevs);
  }
  
  
 @@ -258,11 +270,13 @@ void qemuReattachPciDevice(pciDevice *dev, struct 
 qemud_driver *driver)
  
  
  void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
 +