From rjones at redhat.com Wed Jul 1 08:33:19 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 09:33:19 +0100 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <200906301831.n5UIVjjP000981@raspberry.lat.com> References: <20090630154731.GB7792@amd.home.annexia.org> <200906301831.n5UIVjjP000981@raspberry.lat.com> Message-ID: <20090701083319.GA10768@amd.home.annexia.org> On Tue, Jun 30, 2009 at 02:31:45PM -0400, Rich Mahn wrote: > RuntimeError: could not open display You need to make sure your $DISPLAY variable is passed when you become root. Or just run virt-manager as normal user - it's designed to use PolicyKit to acquire the right permissions. > 2. virsh seems to work as root. It lists the domains, anyhow. > > 3. When I try to create a new domain sometimes it looks like it is > working until it is actually supposed to start. Then nothing > seems to happen. I don't know what processes to look for via > 'ps', but I suspect whatever started died almost immediately. > NOTE: this is what happens if I don't specify any virtual disk > storge. qemu prevents domains from starting without storage. > 4. Creating exactly the same domain with virtual disk storage, when > it tries to create the domain I get the popup error "Unable to compelte > install: internal error Domain didn't show up." > The detail of the error is this: Look at the log file (/var/log/libvirt/qemu IIRC). > 5. For the first case described in 3 above, the virt-manager shows the > domain as running. virsh also shows it as running. However, if I > try to terminate it, shut it down, or whatever (even restart later), > I get this error: [more bugs elided] The libvirt which was in F11-Preview was really broken. Upgrade to the new version in updates-testing and reboot to fix everything. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From rjones at redhat.com Wed Jul 1 08:37:51 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 09:37:51 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> Message-ID: <20090701083751.GA10894@amd.home.annexia.org> On Tue, Jun 30, 2009 at 02:09:17PM -0600, Jerry James wrote: > On Tue, Jun 30, 2009 at 12:31 AM, Dor Laor wrote: > > It might be due to different image caching defaults. > > Can you grab the current command line of qemu and change -drive file=xxxx,..,cache=writeback and retest? > > As far as I can tell, virt-manager doesn't use the -drive option, but > just passes the name of the hard disk image as the last command line > argument. I don't think this is correct. > The virt-manager concept seems nice, but I abandoned it after using it > for only a short time in F-10 because (a) it didn't give me an easy > way to see what options it ultimately passed to qemu-kvm, and (b) it > didn't give me a way to fiddle with nonstandard options. It looks > like I'm probably going to abandon it again in F-11 after only using > it for a short time, for exactly the same reasons. libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen different virtualization systems, giving you the benefit of abstracting the details of the hypervisor from the management tools. So for that reason we don't support tweaking the qemu command line arbitrarily. However if there are particular features of qemu or KVM that you think we should support, please raise them. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From jim at meyering.net Wed Jul 1 14:08:33 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 16:08:33 +0200 Subject: [fedora-virt] [PATCH] don't dereference or free undefined "msg" upon OOM Message-ID: <87y6r81ony.fsf@meyering.net> Hi Rich, Here's a tiny patch to prevent misbehavior on an OOM failure: I prefer the decl-after-stmt (c99) syntax, but if you're not assuming that already, just move the declaration of err "up". >From bb57a823975019ab1be6f5f88e8276b53e8b4023 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 1 Jul 2009 15:45:01 +0200 Subject: [PATCH] don't dereference or free undefined "msg" upon OOM * src/guestfs.c (guestfs_error): Handle failing vasprintf. --- src/guestfs.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/src/guestfs.c b/src/guestfs.c index 5743a07..87b0d86 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -404,9 +404,11 @@ guestfs_error (guestfs_h *g, const char *fs, ...) char *msg; va_start (args, fs); - vasprintf (&msg, fs, args); + int err = vasprintf (&msg, fs, args); va_end (args); + if (err < 0) return; + if (g->error_cb) g->error_cb (g, g->error_cb_data, msg); set_last_error (g, msg); -- 1.6.3.3.483.g4f5e From jim at meyering.net Wed Jul 1 14:11:50 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 16:11:50 +0200 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements Message-ID: <87skhg1oih.fsf@meyering.net> Hi Rich, Looking at the sole remaining uses of asprintf, I noticed these and some realloc/strdup results that needed to be checked. Re asprintf, note that one must always check it for failure, and when it fails, you cannot use the (undefined) pointer result. Obviously this patch is just for reference, i.e, not to apply. >From 7b7df29516dad78a3c815ea1ef301da89d4b5323 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 1 Jul 2009 16:09:33 +0200 Subject: [PATCH] add comments suggesting memory-handling improvements * fish/destpaths.c: Don't deref NULL or undef on failed heap alloc. --- fish/destpaths.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fish/destpaths.c b/fish/destpaths.c index 6cddafa..a5ece2a 100644 --- a/fish/destpaths.c +++ b/fish/destpaths.c @@ -55,7 +55,7 @@ complete_dest_paths_generator (const char *text, int state) static int len, index; static char **words = NULL; - static int nr_words = 0; + static int nr_words = 0; // nr_words should be size_t char *word; guestfs_error_handler_cb old_error_cb; void *old_error_cb_data; @@ -75,6 +75,7 @@ complete_dest_paths_generator (const char *text, int state) char **strs; int i, n; + // len should be of type size_t; index and "i", too len = strlen (text); index = 0; @@ -92,8 +93,11 @@ complete_dest_paths_generator (const char *text, int state) #define APPEND_STRS_AND_FREE \ if (strs) { \ + // n should be unsigned, like size_t n = count_strings (strs); \ + // handle the case in which sizeof (char *) * (nr_words + n)) overflows words = realloc (words, sizeof (char *) * (nr_words + n)); \ + // handle failed realloc for (i = 0; i < n; ++i) \ words[nr_words++] = strs[i]; \ free (strs); \ @@ -120,17 +124,20 @@ complete_dest_paths_generator (const char *text, int state) p = strrchr (text, '/'); dir = p && p > text ? strndup (text, p - text) : strdup ("/"); + // handle failed strdup strs = guestfs_ls (g, dir); /* Prepend directory to names. */ if (strs) { for (i = 0; strs[i]; ++i) { + int err; p = NULL; if (strcmp (dir, "/") == 0) - asprintf (&p, "/%s", strs[i]); + err = asprintf (&p, "/%s", strs[i]); else - asprintf (&p, "%s/%s", dir, strs[i]); + err = asprintf (&p, "%s/%s", dir, strs[i]); + // handle failed asprintf, i.e., err < 0 free (strs[i]); strs[i] = p; } -- 1.6.3.3.483.g4f5e From rjones at redhat.com Wed Jul 1 14:23:20 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 15:23:20 +0100 Subject: [fedora-virt] [PATCH] don't dereference or free undefined "msg" upon OOM In-Reply-To: <87y6r81ony.fsf@meyering.net> References: <87y6r81ony.fsf@meyering.net> Message-ID: <20090701142320.GA15919@amd.home.annexia.org> On Wed, Jul 01, 2009 at 04:08:33PM +0200, Jim Meyering wrote: > Here's a tiny patch to prevent misbehavior on an OOM failure: > I prefer the decl-after-stmt (c99) syntax, but if you're > not assuming that already, just move the declaration of err "up". I started off by declaring all the variables at the top of each function, but after a while I got fed up with that, so a lot of the code uses both styles ... > >From bb57a823975019ab1be6f5f88e8276b53e8b4023 Mon Sep 17 00:00:00 2001 > From: Jim Meyering > Date: Wed, 1 Jul 2009 15:45:01 +0200 > Subject: [PATCH] don't dereference or free undefined "msg" upon OOM > > * src/guestfs.c (guestfs_error): Handle failing vasprintf. > --- > src/guestfs.c | 4 +++- > 1 files changed, 3 insertions(+), 1 deletions(-) > > diff --git a/src/guestfs.c b/src/guestfs.c > index 5743a07..87b0d86 100644 > --- a/src/guestfs.c > +++ b/src/guestfs.c > @@ -404,9 +404,11 @@ guestfs_error (guestfs_h *g, const char *fs, ...) > char *msg; > > va_start (args, fs); > - vasprintf (&msg, fs, args); > + int err = vasprintf (&msg, fs, args); > va_end (args); > > + if (err < 0) return; > + > if (g->error_cb) g->error_cb (g, g->error_cb_data, msg); > set_last_error (g, msg); > > -- > 1.6.3.3.483.g4f5e ACK. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From rich at lat.com Wed Jul 1 14:25:37 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 01 Jul 2009 10:25:37 -0400 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: Your message of "Wed, 01 Jul 2009 09:33:19 BST." <20090701083319.GA10768@amd.home.annexia.org> Message-ID: <200907011425.n61EPbMX009668@raspberry.lat.com> > On Tue, Jun 30, 2009 at 02:31:45PM -0400, Rich Mahn wrote: > > RuntimeError: could not open display > You need to make sure your $DISPLAY variable is passed when you become > root. Or just run virt-manager as normal user - it's designed to use > PolicyKit to acquire the right permissions. It's not DISPLAY that's the problem. I don't know exactly what it is, but when I changed back to gdm from kdm, the root type problems went away. > > 2. virsh seems to work as root. It lists the domains, anyhow. > > > > 3. When I try to create a new domain sometimes it looks like it is > > working until it is actually supposed to start. Then nothing > > seems to happen. I don't know what processes to look for via > > 'ps', but I suspect whatever started died almost immediately. > > NOTE: this is what happens if I don't specify any virtual disk > > storge. > qemu prevents domains from starting without storage. It seems to work fine with just a cd-image. > > 4. Creating exactly the same domain with virtual disk storage, when > > it tries to create the domain I get the popup error "Unable to compelte > > install: internal error Domain didn't show up." > > The detail of the error is this: > Look at the log file (/var/log/libvirt/qemu IIRC). VERY good advice. From the log file I learned that the startup problems I had were due to the cdr iso file being on nfs storage. Once I copied it to the local disk it worked fine. Changing the virt_use_nfs, qemu_use_nfs didn't work because virt-manager tries to set the security label, and that's not supported on this version of nfs. > > 5. For the first case described in 3 above, the virt-manager shows the > > domain as running. virsh also shows it as running. However, if I > > try to terminate it, shut it down, or whatever (even restart later), > > I get this error: > [more bugs elided] > The libvirt which was in F11-Preview was really broken. Upgrade to > the new version in updates-testing and reboot to fix everything. I am using whatever the current F11/x86_64 updates has. I couldn't find any libvirt in updates-testing. > Rich. great name!!! > -- > Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones > virt-df lists disk usage of guests without needing to install any > software inside the virtual machine. Supports Linux and Windows. > http://et.redhat.com/~rjones/virt-df/ From rich at lat.com Wed Jul 1 14:28:46 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 01 Jul 2009 10:28:46 -0400 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: Your message of "Wed, 01 Jul 2009 09:37:51 BST." <20090701083751.GA10894@amd.home.annexia.org> Message-ID: <200907011428.n61ESktu009707@raspberry.lat.com> > libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen > different virtualization systems, giving you the benefit of > abstracting the details of the hypervisor from the management tools. > So for that reason we don't support tweaking the qemu command line > arbitrarily. However if there are particular features of qemu or KVM > that you think we should support, please raise them. I would like to see a feature equivalent to the -no-reboot in qemu. When I manually shutdown a virtual machine I don't like it automatically booting back up. From jim at meyering.net Wed Jul 1 14:32:16 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 16:32:16 +0200 Subject: [fedora-virt] [PATCH] don't dereference or free undefined "msg" upon OOM In-Reply-To: <20090701142320.GA15919@amd.home.annexia.org> (Richard W. M. Jones's message of "Wed, 1 Jul 2009 15:23:20 +0100") References: <87y6r81ony.fsf@meyering.net> <20090701142320.GA15919@amd.home.annexia.org> Message-ID: <87ab3o1nkf.fsf@meyering.net> Richard W.M. Jones wrote: >> Subject: [PATCH] don't dereference or free undefined "msg" upon OOM ... > ACK. Thanks for the quick review. Should I push that (I'd have to give myself permission)? From rjones at redhat.com Wed Jul 1 14:34:41 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 15:34:41 +0100 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <200907011425.n61EPbMX009668@raspberry.lat.com> References: <20090701083319.GA10768@amd.home.annexia.org> <200907011425.n61EPbMX009668@raspberry.lat.com> Message-ID: <20090701143441.GA16309@amd.home.annexia.org> On Wed, Jul 01, 2009 at 10:25:37AM -0400, Rich Mahn wrote: > VERY good advice. From the log file I learned that the startup > problems I had were due to the cdr iso file being on nfs storage. > Once I copied it to the local disk it worked fine. Changing the > virt_use_nfs, qemu_use_nfs didn't work because virt-manager tries > to set the security label, and that's not supported on this version > of nfs. This is a bug - any ideas Dan? Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Wed Jul 1 14:39:26 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 15:39:26 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <200907011428.n61ESktu009707@raspberry.lat.com> References: <20090701083751.GA10894@amd.home.annexia.org> <200907011428.n61ESktu009707@raspberry.lat.com> Message-ID: <20090701143926.GB16309@amd.home.annexia.org> On Wed, Jul 01, 2009 at 10:28:46AM -0400, Rich Mahn wrote: > > > libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen > > different virtualization systems, giving you the benefit of > > abstracting the details of the hypervisor from the management tools. > > So for that reason we don't support tweaking the qemu command line > > arbitrarily. However if there are particular features of qemu or KVM > > that you think we should support, please raise them. > > > I would like to see a feature equivalent to the -no-reboot in qemu. > When I manually shutdown a virtual machine I don't like it automatically > booting back up. We support this already. You have to set this: destroy See: http://libvirt.org/formatdomain.html#elementsLifecycle To change the domain XML configuration use 'virsh edit '. There might also be a way to change this setting in virt-manager. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Wed Jul 1 14:49:08 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 15:49:08 +0100 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <87skhg1oih.fsf@meyering.net> References: <87skhg1oih.fsf@meyering.net> Message-ID: <20090701144908.GA16409@amd.home.annexia.org> On Wed, Jul 01, 2009 at 04:11:50PM +0200, Jim Meyering wrote: > Hi Rich, > > Looking at the sole remaining uses of asprintf, I noticed these > and some realloc/strdup results that needed to be checked. > > Re asprintf, note that one must always check it for failure, > and when it fails, you cannot use the (undefined) pointer result. > Obviously this patch is just for reference, i.e, not to apply. > > >From 7b7df29516dad78a3c815ea1ef301da89d4b5323 Mon Sep 17 00:00:00 2001 > From: Jim Meyering > Date: Wed, 1 Jul 2009 16:09:33 +0200 > Subject: [PATCH] add comments suggesting memory-handling improvements > > * fish/destpaths.c: Don't deref NULL or undef on failed heap alloc. > --- > fish/destpaths.c | 13 ++++++++++--- > 1 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/fish/destpaths.c b/fish/destpaths.c > index 6cddafa..a5ece2a 100644 > --- a/fish/destpaths.c > +++ b/fish/destpaths.c > @@ -55,7 +55,7 @@ complete_dest_paths_generator (const char *text, int state) > > static int len, index; > static char **words = NULL; > - static int nr_words = 0; > + static int nr_words = 0; // nr_words should be size_t > char *word; > guestfs_error_handler_cb old_error_cb; > void *old_error_cb_data; > @@ -75,6 +75,7 @@ complete_dest_paths_generator (const char *text, int state) > char **strs; > int i, n; > > + // len should be of type size_t; index and "i", too > len = strlen (text); > index = 0; > > @@ -92,8 +93,11 @@ complete_dest_paths_generator (const char *text, int state) > > #define APPEND_STRS_AND_FREE \ > if (strs) { \ > + // n should be unsigned, like size_t > n = count_strings (strs); \ > + // handle the case in which sizeof (char *) * (nr_words + n)) overflows > words = realloc (words, sizeof (char *) * (nr_words + n)); \ > + // handle failed realloc > for (i = 0; i < n; ++i) \ > words[nr_words++] = strs[i]; \ > free (strs); \ > @@ -120,17 +124,20 @@ complete_dest_paths_generator (const char *text, int state) > > p = strrchr (text, '/'); > dir = p && p > text ? strndup (text, p - text) : strdup ("/"); > + // handle failed strdup [etc] Was the plan to add these comments to the source now in the hope we'd fix it in future? Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From tom.horsley at att.net Wed Jul 1 14:57:15 2009 From: tom.horsley at att.net (Tom Horsley) Date: Wed, 1 Jul 2009 10:57:15 -0400 Subject: [fedora-virt] disk perf again Message-ID: <20090701105715.5fb3f9ff@zooty> In my xen virtual machines, I found that switching my disk image files from file: to tap:aio: made the machines (all HVMs) run much better with far fewer hangs and glitches. If I were to try to run with KVM rather than XEN, is there some equivalent of something like tap:aio that provides better disk performance, or is the KVM equivalent of file: the only way to access a disk image in a file? (I hasten to add I have absolutely no idea what the heck file: versus tap:aio: means, I just tried it when I saw it mentioned somewhere and it worked much much better :-). From rjones at redhat.com Wed Jul 1 15:13:23 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 16:13:23 +0100 Subject: [fedora-virt] disk perf again In-Reply-To: <20090701105715.5fb3f9ff@zooty> References: <20090701105715.5fb3f9ff@zooty> Message-ID: <20090701151323.GB16409@amd.home.annexia.org> On Wed, Jul 01, 2009 at 10:57:15AM -0400, Tom Horsley wrote: > In my xen virtual machines, I found that switching my disk > image files from file: to tap:aio: made the machines (all > HVMs) run much better with far fewer hangs and glitches. > > If I were to try to run with KVM rather than XEN, is there > some equivalent of something like tap:aio that provides > better disk performance, or is the KVM equivalent of file: > the only way to access a disk image in a file? > > (I hasten to add I have absolutely no idea what the > heck file: versus tap:aio: means, I just tried it when > I saw it mentioned somewhere and it worked much much > better :-). Yes there certainly is. There are two issues here. Issue (1): is the virtual disk backed by a file or a partition/LVM? If the virtual disk sits in a file on a filesystem, then to access that we have to do through the whole filesystem stack on the host. If the virtual disk sites in a partition or LV, then there is much less overhead on the host. Issue (2): does the guest use fullvirt emulation or paravirtualization (PV) to access the virtual disk? Full emulation of (eg.) IDE and SCSI devices is very inefficient. It's far better if the guest cooperates with the host (paravirtualization). The fastest case will be (1) == partition/LVM, (2) == PV drivers. On Xen, file: -> tap:aio: essentially converts the guest from using full emulation to paravirt drivers. On KVM, you can do the same thing by installing virtio drivers (not just for disk, for network too). If you are installing a relatively recent guest on a relatively recent host (eg. Fedora 10+ on Fedora 10+, or RHEL 5.3 on Fedora 11), then virtio should just work. You can tell if the guest can support Xen PV drivers or virtio using our virt-inspector tool, or looking inside the guest at the start-up messages. http://wiki.libvirt.org/page/Virtio Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Wed Jul 1 15:16:18 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 16:16:18 +0100 Subject: [fedora-virt] [PATCH] Change libguestfs to use virtio block devices In-Reply-To: <20090630145123.GA7792@amd.home.annexia.org> References: <20090630145123.GA7792@amd.home.annexia.org> Message-ID: <20090701151618.GC16409@amd.home.annexia.org> On Tue, Jun 30, 2009 at 03:51:23PM +0100, Richard W.M. Jones wrote: > The following set of patches changes libguestfs to use virtio block > devices by default. I pushed this one. One test fails - I'm about to file a bug about that. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Wed Jul 1 15:20:47 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 16:20:47 +0100 Subject: [fedora-virt] [PATCH] Change libguestfs to use virtio block devices In-Reply-To: <20090701151618.GC16409@amd.home.annexia.org> References: <20090630145123.GA7792@amd.home.annexia.org> <20090701151618.GC16409@amd.home.annexia.org> Message-ID: <20090701152047.GD16409@amd.home.annexia.org> On Wed, Jul 01, 2009 at 04:16:18PM +0100, Richard W.M. Jones wrote: > One test fails - I'm about to file a bug about that. https://bugzilla.redhat.com/show_bug.cgi?id=509155 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From gene at czarc.net Wed Jul 1 15:32:13 2009 From: gene at czarc.net (Gene Czarcinski) Date: Wed, 1 Jul 2009 11:32:13 -0400 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <20090701143441.GA16309@amd.home.annexia.org> References: <20090701083319.GA10768@amd.home.annexia.org> <200907011425.n61EPbMX009668@raspberry.lat.com> <20090701143441.GA16309@amd.home.annexia.org> Message-ID: <200907011132.13743.gene@czarc.net> On Wednesday 01 July 2009 10:34:41 Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 10:25:37AM -0400, Rich Mahn wrote: > > VERY good advice. From the log file I learned that the startup > > problems I had were due to the cdr iso file being on nfs storage. > > Once I copied it to the local disk it worked fine. Changing the > > virt_use_nfs, qemu_use_nfs didn't work because virt-manager tries > > to set the security label, and that's not supported on this version > > of nfs. > > This is a bug - any ideas Dan? At the very least, I consider this a bug and have reported it as such: https://bugzilla.redhat.com/show_bug.cgi?id=508865 I suspect this is the result of trying to use SELinux to protect everything and the mandatory access control idea that everything is disallowed except that which is explicitly permitted. But, I just do not understand what and why CD/DVD images and devices are being protected. Furthermore, when virtualization changes a file's context (including /dev/sr0), could this effect other valid usage of these files/devices? If there is no effect for other applications, then just what is protected? Gene From berrange at redhat.com Wed Jul 1 15:56:53 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 1 Jul 2009 16:56:53 +0100 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <200907011425.n61EPbMX009668@raspberry.lat.com> References: <20090701083319.GA10768@amd.home.annexia.org> <200907011425.n61EPbMX009668@raspberry.lat.com> Message-ID: <20090701155653.GA24296@redhat.com> On Wed, Jul 01, 2009 at 10:25:37AM -0400, Rich Mahn wrote: > > > 4. Creating exactly the same domain with virtual disk storage, when > > > it tries to create the domain I get the popup error "Unable to compelte > > > install: internal error Domain didn't show up." > > > The detail of the error is this: > > > Look at the log file (/var/log/libvirt/qemu IIRC). > > VERY good advice. From the log file I learned that the startup > problems I had were due to the cdr iso file being on nfs storage. > Once I copied it to the local disk it worked fine. Changing the > virt_use_nfs, qemu_use_nfs didn't work because virt-manager tries > to set the security label, and that's not supported on this version > of nfs. Thats a bug in libvirt https://bugzilla.redhat.com/show_bug.cgi?id=507555 Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From gene at czarc.net Wed Jul 1 16:03:20 2009 From: gene at czarc.net (Gene Czarcinski) Date: Wed, 1 Jul 2009 12:03:20 -0400 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <20090701083319.GA10768@amd.home.annexia.org> References: <20090630154731.GB7792@amd.home.annexia.org> <200906301831.n5UIVjjP000981@raspberry.lat.com> <20090701083319.GA10768@amd.home.annexia.org> Message-ID: <200907011203.20973.gene@czarc.net> On Wednesday 01 July 2009 04:33:19 Richard W.M. Jones wrote: > > 5. For the first case described in 3 above, the virt-manager shows the > > domain as running. virsh also shows it as running. However, if I > > try to terminate it, shut it down, or whatever (even restart later), > > I get this error: > > [more bugs elided] > > The libvirt which was in F11-Preview was really broken. Upgrade to > the new version in updates-testing and reboot to fix everything. Can you be a little more specific as to which virtualization packages should be pulled from updates-testing. Looking over what is available as of today, it is not obvious that there are any such packages. As of this date, I am up-to- date with respect to any regular updates available. Gene From rjones at redhat.com Wed Jul 1 16:19:50 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 17:19:50 +0100 Subject: [fedora-virt] best Fedora virtualization In-Reply-To: <200907011203.20973.gene@czarc.net> References: <20090630154731.GB7792@amd.home.annexia.org> <200906301831.n5UIVjjP000981@raspberry.lat.com> <20090701083319.GA10768@amd.home.annexia.org> <200907011203.20973.gene@czarc.net> Message-ID: <20090701161950.GA17141@amd.home.annexia.org> On Wed, Jul 01, 2009 at 12:03:20PM -0400, Gene Czarcinski wrote: > On Wednesday 01 July 2009 04:33:19 Richard W.M. Jones wrote: > > > 5. For the first case described in 3 above, the virt-manager shows the > > > domain as running. virsh also shows it as running. However, if I > > > try to terminate it, shut it down, or whatever (even restart later), > > > I get this error: > > > > [more bugs elided] > > > > The libvirt which was in F11-Preview was really broken. Upgrade to > > the new version in updates-testing and reboot to fix everything. > > Can you be a little more specific as to which virtualization packages should be > pulled from updates-testing. Looking over what is available as of today, it > is not obvious that there are any such packages. As of this date, I am up-to- > date with respect to any regular updates available. In that case you should be fine. I have a mix of boxes on (old) Rawhide, F11-Preview and so on, and on some of them I had to upgrade libvirt (only) to get guest installation working. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From jim at meyering.net Wed Jul 1 16:21:05 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 18:21:05 +0200 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <20090701144908.GA16409@amd.home.annexia.org> (Richard W. M. Jones's message of "Wed, 1 Jul 2009 15:49:08 +0100") References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> Message-ID: <87ws6sz85q.fsf@meyering.net> Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 04:11:50PM +0200, Jim Meyering wrote: >> Re asprintf, note that one must always check it for failure, >> and when it fails, you cannot use the (undefined) pointer result. >> Obviously this patch is just for reference, i.e, not to apply. ^^^^^^^^^^^^^ >> >From 7b7df29516dad78a3c815ea1ef301da89d4b5323 Mon Sep 17 00:00:00 2001 >> From: Jim Meyering >> Date: Wed, 1 Jul 2009 16:09:33 +0200 >> Subject: [PATCH] add comments suggesting memory-handling improvements ... >> #define APPEND_STRS_AND_FREE \ >> if (strs) { \ >> + // n should be unsigned, like size_t >> n = count_strings (strs); \ >> + // handle the case in which sizeof (char *) * (nr_words + n)) overflows >> words = realloc (words, sizeof (char *) * (nr_words + n)); \ >> + // handle failed realloc >> for (i = 0; i < n; ++i) \ >> words[nr_words++] = strs[i]; \ >> free (strs); \ >> @@ -120,17 +124,20 @@ complete_dest_paths_generator (const char *text, int state) >> >> p = strrchr (text, '/'); >> dir = p && p > text ? strndup (text, p - text) : strdup ("/"); >> + // handle failed strdup > [etc] > > Was the plan to add these comments to the source now in the hope > we'd fix it in future? Please, don't apply that ;-) It's not even syntactically correct. I've include a patch below. It would have been easier and cleaner *looking* to use functions like xrealloc, xstrdup, etc. that exit upon failure here. But since nothing else seems to exit from this code, I bit the bullet: (this compiles, but "make check" hasn't completed yet) Hmm... new test failures on F11 (details below) But I'd just pulled latest and rebased, too. >From 77b4a54834cd3d3e6994508104334f501f5d99f1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 1 Jul 2009 16:09:33 +0200 Subject: [PATCH] fish: handle some out-of-memory conditions * fish/destpaths.c (xalloc_oversized): Define. (complete_dest_paths_generator): Use size_t as type for a few variables, rather than int. Don't deref NULL or undef on failed heap alloc. Don't leak on failed realloc. Detect theoretical overflow when count_strings returns a very large number of strings. Handle asprintf failure. (APPEND_STRS_AND_FREE): Rewrite as do {...}while(0), so that each use can/must be followed by a semicolon. Better for auto-formatters. --- fish/destpaths.c | 91 ++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 62 insertions(+), 29 deletions(-) diff --git a/fish/destpaths.c b/fish/destpaths.c index 6cddafa..90970de 100644 --- a/fish/destpaths.c +++ b/fish/destpaths.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include #include +#include #include #ifdef HAVE_LIBREADLINE @@ -32,6 +33,22 @@ #include "fish.h" +// From gnulib's xalloc.h: +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + /* Readline completion for paths on the guest filesystem, also for * devices and LVM names. */ @@ -53,9 +70,9 @@ complete_dest_paths_generator (const char *text, int state) { #ifdef HAVE_LIBREADLINE - static int len, index; + static size_t len, index; static char **words = NULL; - static int nr_words = 0; + static size_t nr_words = 0; char *word; guestfs_error_handler_cb old_error_cb; void *old_error_cb_data; @@ -73,12 +90,12 @@ complete_dest_paths_generator (const char *text, int state) if (!state) { char **strs; - int i, n; len = strlen (text); index = 0; if (words) { + size_t i; /* NB. 'words' array is NOT NULL-terminated. */ for (i = 0; i < nr_words; ++i) free (words[i]); @@ -90,26 +107,38 @@ complete_dest_paths_generator (const char *text, int state) SAVE_ERROR_CB +/* Silently do nothing if an allocation fails */ #define APPEND_STRS_AND_FREE \ + do { \ if (strs) { \ - n = count_strings (strs); \ - words = realloc (words, sizeof (char *) * (nr_words + n)); \ - for (i = 0; i < n; ++i) \ - words[nr_words++] = strs[i]; \ - free (strs); \ - } + size_t n = count_strings (strs); \ + if ( ! xalloc_oversized (nr_words + n, sizeof (char *))) { \ + char *w = realloc (words, sizeof (char *) * (nr_words + n)); \ + if (w == NULL) { \ + free (words); \ + words = NULL; \ + nr_words = 0; \ + } else { \ + size_t i; \ + for (i = 0; i < n; ++i) \ + words[nr_words++] = strs[i]; \ + } \ + free (strs); \ + } \ + } \ + } while (0) /* Is it a device? */ if (len < 5 || strncmp (text, "/dev/", 5) == 0) { /* Get a list of everything that can possibly begin with /dev/ */ strs = guestfs_list_devices (g); - APPEND_STRS_AND_FREE + APPEND_STRS_AND_FREE; strs = guestfs_list_partitions (g); - APPEND_STRS_AND_FREE + APPEND_STRS_AND_FREE; strs = guestfs_lvs (g); - APPEND_STRS_AND_FREE + APPEND_STRS_AND_FREE; } if (len < 1 || text[0] == '/') { @@ -120,24 +149,28 @@ complete_dest_paths_generator (const char *text, int state) p = strrchr (text, '/'); dir = p && p > text ? strndup (text, p - text) : strdup ("/"); - - strs = guestfs_ls (g, dir); - - /* Prepend directory to names. */ - if (strs) { - for (i = 0; strs[i]; ++i) { - p = NULL; - if (strcmp (dir, "/") == 0) - asprintf (&p, "/%s", strs[i]); - else - asprintf (&p, "%s/%s", dir, strs[i]); - free (strs[i]); - strs[i] = p; + if (dir) { + strs = guestfs_ls (g, dir); + + /* Prepend directory to names. */ + if (strs) { + size_t i; + for (i = 0; strs[i]; ++i) { + int err; + if (strcmp (dir, "/") == 0) + err = asprintf (&p, "/%s", strs[i]); + else + err = asprintf (&p, "%s/%s", dir, strs[i]); + if (0 <= err) { + free (strs[i]); + strs[i] = p; + } + } } - } - free (dir); - APPEND_STRS_AND_FREE + free (dir); + APPEND_STRS_AND_FREE; + } } /* else ... In theory we could complete other things here such as VG -- 1.6.3.3.483.g4f5e 16/174 test_head_n_1 mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so test_head_n_1 FAILED ... 25/174 test_glob_expand_0 mount: /dev/vda1 on /: mount: unknown filesystem type 'lvm2pv' test_glob_expand_0 FAILED 26/174 test_glob_expand_1 /sbin/sfdisk /dev/vda: external command failed test_glob_expand_1 FAILED 27/174 test_glob_expand_2 /sbin/sfdisk /dev/vda: external command failed test_glob_expand_2 FAILED 28/174 test_ntfs_3g_probe_0 /sbin/sfdisk /dev/vda: external command failed test_ntfs_3g_probe_0 FAILED 29/174 test_ntfs_3g_probe_1 /sbin/sfdisk /dev/vda: external command failed test_ntfs_3g_probe_1 FAILED ... 32/174 test_find_1 mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so test_find_1 FAILED 33/174 test_find_2 34/174 test_lvresize_0 35/174 test_zerofree_0 vgremove: VG: File descriptor 3 (socket:[5132]) leaked on lvm invocation. Parent PID 1: /dev/dm-0: stat failed: No such file or directory Path /dev/dm-0 no longer valid for device(253,0) /dev/block/253:0: stat failed: No such file or directory Pa test_zerofree_0 FAILED 36/174 test_hexdump_0 open: /new: Stale NFS file handle test_hexdump_0 FAILED 37/174 test_hexdump_1 38/174 test_strings_e_0 open: /new: Stale NFS file handle test_strings_e_0 FAILED 39/174 test_strings_e_1 test_strings_e_1 skipped (reason: test disabled in generator) 40/174 test_strings_0 ... 52/174 test_cp_1 mount: /dev/vda1 on /: mount: Stale NFS file handle test_cp_1 FAILED From rjones at redhat.com Wed Jul 1 16:32:24 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 17:32:24 +0100 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <87ws6sz85q.fsf@meyering.net> References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> Message-ID: <20090701163224.GF14689@amd.home.annexia.org> On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: > 16/174 test_head_n_1 > mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, > missing codepage or helper program, or other error > In some cases useful info is found in syslog - try > dmesg | tail or so > test_head_n_1 FAILED > ... > 25/174 test_glob_expand_0 > mount: /dev/vda1 on /: mount: unknown filesystem type 'lvm2pv' > test_glob_expand_0 FAILED Yes, sorry, I just broke the test suite. Fix coming up as soon as I know it passes 'make check' ... Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From rjones at redhat.com Wed Jul 1 16:38:05 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 17:38:05 +0100 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <87ws6sz85q.fsf@meyering.net> References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> Message-ID: <20090701163805.GG14689@amd.home.annexia.org> On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: > I've include a patch below. It would have been easier and cleaner *looking* > to use functions like xrealloc, xstrdup, etc. that exit upon failure here. > But since nothing else seems to exit from this code, I bit the bullet: > (this compiles, but "make check" hasn't completed yet) Yes, I agree. There's not very much that guestfish can do if it runs out of memory, and the most sensible thing would be just to exit with an error (or abort). > Hmm... new test failures on F11 (details below) > But I'd just pulled latest and rebased, too. > > >From 77b4a54834cd3d3e6994508104334f501f5d99f1 Mon Sep 17 00:00:00 2001 > From: Jim Meyering > Date: Wed, 1 Jul 2009 16:09:33 +0200 > Subject: [PATCH] fish: handle some out-of-memory conditions > > * fish/destpaths.c (xalloc_oversized): Define. > (complete_dest_paths_generator): Use size_t as type for a few > variables, rather than int. > Don't deref NULL or undef on failed heap alloc. > Don't leak on failed realloc. > Detect theoretical overflow when count_strings returns a very > large number of strings. > Handle asprintf failure. > (APPEND_STRS_AND_FREE): Rewrite as do {...}while(0), so that each use > can/must be followed by a semicolon. Better for auto-formatters. > --- > fish/destpaths.c | 91 ++++++++++++++++++++++++++++++++++++----------------- > 1 files changed, 62 insertions(+), 29 deletions(-) > > diff --git a/fish/destpaths.c b/fish/destpaths.c > index 6cddafa..90970de 100644 > --- a/fish/destpaths.c > +++ b/fish/destpaths.c > @@ -1,5 +1,5 @@ > /* guestfish - the filesystem interactive shell > - * Copyright (C) 2009 Red Hat Inc. > + * Copyright (C) 2009 Red Hat Inc. Strange, this doesn't look like any change? > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > @@ -22,6 +22,7 @@ > > #include > #include > +#include > #include > > #ifdef HAVE_LIBREADLINE > @@ -32,6 +33,22 @@ > > #include "fish.h" > > +// From gnulib's xalloc.h: > +/* Return 1 if an array of N objects, each of size S, cannot exist due > + to size arithmetic overflow. S must be positive and N must be > + nonnegative. This is a macro, not an inline function, so that it > + works correctly even when SIZE_MAX < N. > + > + By gnulib convention, SIZE_MAX represents overflow in size > + calculations, so the conservative dividend to use here is > + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. > + However, malloc (SIZE_MAX) fails on all known hosts where > + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for > + exactly-SIZE_MAX allocations on such hosts; this avoids a test and > + branch when S is known to be 1. */ > +# define xalloc_oversized(n, s) \ > + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) > + > /* Readline completion for paths on the guest filesystem, also for > * devices and LVM names. > */ > @@ -53,9 +70,9 @@ complete_dest_paths_generator (const char *text, int state) > { > #ifdef HAVE_LIBREADLINE > > - static int len, index; > + static size_t len, index; > static char **words = NULL; > - static int nr_words = 0; > + static size_t nr_words = 0; > char *word; > guestfs_error_handler_cb old_error_cb; > void *old_error_cb_data; > @@ -73,12 +90,12 @@ complete_dest_paths_generator (const char *text, int state) > > if (!state) { > char **strs; > - int i, n; > > len = strlen (text); > index = 0; > > if (words) { > + size_t i; > /* NB. 'words' array is NOT NULL-terminated. */ > for (i = 0; i < nr_words; ++i) > free (words[i]); > @@ -90,26 +107,38 @@ complete_dest_paths_generator (const char *text, int state) > > SAVE_ERROR_CB > > +/* Silently do nothing if an allocation fails */ > #define APPEND_STRS_AND_FREE \ > + do { \ > if (strs) { \ > - n = count_strings (strs); \ > - words = realloc (words, sizeof (char *) * (nr_words + n)); \ > - for (i = 0; i < n; ++i) \ > - words[nr_words++] = strs[i]; \ > - free (strs); \ > - } > + size_t n = count_strings (strs); \ > + if ( ! xalloc_oversized (nr_words + n, sizeof (char *))) { \ > + char *w = realloc (words, sizeof (char *) * (nr_words + n)); \ > + if (w == NULL) { \ > + free (words); \ > + words = NULL; \ > + nr_words = 0; \ > + } else { \ > + size_t i; \ > + for (i = 0; i < n; ++i) \ > + words[nr_words++] = strs[i]; \ > + } \ > + free (strs); \ > + } \ > + } \ > + } while (0) > > /* Is it a device? */ > if (len < 5 || strncmp (text, "/dev/", 5) == 0) { > /* Get a list of everything that can possibly begin with /dev/ */ > strs = guestfs_list_devices (g); > - APPEND_STRS_AND_FREE > + APPEND_STRS_AND_FREE; > > strs = guestfs_list_partitions (g); > - APPEND_STRS_AND_FREE > + APPEND_STRS_AND_FREE; > > strs = guestfs_lvs (g); > - APPEND_STRS_AND_FREE > + APPEND_STRS_AND_FREE; > } Yes, this all makes sense. > if (len < 1 || text[0] == '/') { > @@ -120,24 +149,28 @@ complete_dest_paths_generator (const char *text, int state) > > p = strrchr (text, '/'); > dir = p && p > text ? strndup (text, p - text) : strdup ("/"); > - > - strs = guestfs_ls (g, dir); > - > - /* Prepend directory to names. */ > - if (strs) { > - for (i = 0; strs[i]; ++i) { > - p = NULL; > - if (strcmp (dir, "/") == 0) > - asprintf (&p, "/%s", strs[i]); > - else > - asprintf (&p, "%s/%s", dir, strs[i]); > - free (strs[i]); > - strs[i] = p; > + if (dir) { > + strs = guestfs_ls (g, dir); > + > + /* Prepend directory to names. */ > + if (strs) { > + size_t i; > + for (i = 0; strs[i]; ++i) { > + int err; > + if (strcmp (dir, "/") == 0) > + err = asprintf (&p, "/%s", strs[i]); > + else > + err = asprintf (&p, "%s/%s", dir, strs[i]); > + if (0 <= err) { > + free (strs[i]); > + strs[i] = p; > + } > + } > } > - } > > - free (dir); > - APPEND_STRS_AND_FREE > + free (dir); > + APPEND_STRS_AND_FREE; > + } > } Yes, all looks good. ACK. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From rjones at redhat.com Wed Jul 1 16:41:09 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 17:41:09 +0100 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <20090701163224.GF14689@amd.home.annexia.org> References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> <20090701163224.GF14689@amd.home.annexia.org> Message-ID: <20090701164109.GA17323@amd.home.annexia.org> On Wed, Jul 01, 2009 at 05:32:24PM +0100, Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: > > 16/174 test_head_n_1 > > mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, > > missing codepage or helper program, or other error > > In some cases useful info is found in syslog - try > > dmesg | tail or so > > test_head_n_1 FAILED > > ... > > 25/174 test_glob_expand_0 > > mount: /dev/vda1 on /: mount: unknown filesystem type 'lvm2pv' > > test_glob_expand_0 FAILED > > Yes, sorry, I just broke the test suite. Fix coming up > as soon as I know it passes 'make check' ... Do you want to try it again now, with the latest from git. Specifically, http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=fe27753ae5925cbe50042e47115364a57aadbbd7 http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=3e2d925717d1dac6b3862e98192c12d1080c2152 http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=99e28249d52ca5495b636e14ae3e4387ee62c8fe Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From jim at meyering.net Wed Jul 1 16:41:47 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 18:41:47 +0200 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <20090701163805.GG14689@amd.home.annexia.org> (Richard W. M. Jones's message of "Wed, 1 Jul 2009 17:38:05 +0100") References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> <20090701163805.GG14689@amd.home.annexia.org> Message-ID: <87my7oz778.fsf@meyering.net> Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: >> I've include a patch below. It would have been easier and cleaner *looking* >> to use functions like xrealloc, xstrdup, etc. that exit upon failure here. >> But since nothing else seems to exit from this code, I bit the bullet: >> (this compiles, but "make check" hasn't completed yet) > > Yes, I agree. There's not very much that guestfish can do if it runs > out of memory, and the most sensible thing would be just to exit with > an error (or abort). > >> Hmm... new test failures on F11 (details below) >> But I'd just pulled latest and rebased, too. >> >> >From 77b4a54834cd3d3e6994508104334f501f5d99f1 Mon Sep 17 00:00:00 2001 >> From: Jim Meyering >> Date: Wed, 1 Jul 2009 16:09:33 +0200 >> Subject: [PATCH] fish: handle some out-of-memory conditions >> >> * fish/destpaths.c (xalloc_oversized): Define. >> (complete_dest_paths_generator): Use size_t as type for a few >> variables, rather than int. >> Don't deref NULL or undef on failed heap alloc. >> Don't leak on failed realloc. >> Detect theoretical overflow when count_strings returns a very >> large number of strings. >> Handle asprintf failure. >> (APPEND_STRS_AND_FREE): Rewrite as do {...}while(0), so that each use >> can/must be followed by a semicolon. Better for auto-formatters. >> --- >> fish/destpaths.c | 91 ++++++++++++++++++++++++++++++++++++----------------- >> 1 files changed, 62 insertions(+), 29 deletions(-) >> >> diff --git a/fish/destpaths.c b/fish/destpaths.c >> index 6cddafa..90970de 100644 >> --- a/fish/destpaths.c >> +++ b/fish/destpaths.c >> @@ -1,5 +1,5 @@ >> /* guestfish - the filesystem interactive shell >> - * Copyright (C) 2009 Red Hat Inc. >> + * Copyright (C) 2009 Red Hat Inc. > > Strange, this doesn't look like any change? As I sent it, I accidentally let a write hook remove the trailing blank on the "- ..." line. I.e., that change (before being munged) removes the sole trailing blank in that file. From dhuff at redhat.com Wed Jul 1 16:50:32 2009 From: dhuff at redhat.com (David Huff) Date: Wed, 01 Jul 2009 12:50:32 -0400 Subject: [fedora-virt] libguestfs and yum Message-ID: <4A4B93D8.2080701@redhat.com> Anyone see any issues with libguestfs and yum working weirdly?? If I mount an disk image with guestfish and try to install new packages with yum, it gives rpmdb errors. However if I "launch" the disk images as a guest in a fill virt container like qemu, there are no rpmdb error and I can install new packages with yum.... Also, if I remove the rpmdb and rebuild via guestfish, then yum seems to be working fine.... command "rm -f /var/lib/rpm/__db.004" command "rpm --rebuilddb" Then yum seems to work: command "yum install vim-enhanced" It looks like yum is still using something outside of guestfish, anyone have any comments/ideas on this?? Thanks, David From jim at meyering.net Wed Jul 1 16:52:14 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 18:52:14 +0200 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <20090701164109.GA17323@amd.home.annexia.org> (Richard W. M. Jones's message of "Wed, 1 Jul 2009 17:41:09 +0100") References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> <20090701163224.GF14689@amd.home.annexia.org> <20090701164109.GA17323@amd.home.annexia.org> Message-ID: <87hbxwz6pt.fsf@meyering.net> Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 05:32:24PM +0100, Richard W.M. Jones wrote: >> On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: >> > 16/174 test_head_n_1 >> > mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, >> > missing codepage or helper program, or other error >> > In some cases useful info is found in syslog - try >> > dmesg | tail or so >> > test_head_n_1 FAILED >> > ... >> > 25/174 test_glob_expand_0 >> > mount: /dev/vda1 on /: mount: unknown filesystem type 'lvm2pv' >> > test_glob_expand_0 FAILED >> >> Yes, sorry, I just broke the test suite. Fix coming up >> as soon as I know it passes 'make check' ... > > Do you want to try it again now, with the latest from git. Rebased and running the tests... 31/174 and counting. From rjones at redhat.com Wed Jul 1 17:00:20 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 1 Jul 2009 18:00:20 +0100 Subject: [fedora-virt] libguestfs and yum In-Reply-To: <4A4B93D8.2080701@redhat.com> References: <4A4B93D8.2080701@redhat.com> Message-ID: <20090701170020.GA17415@amd.home.annexia.org> On Wed, Jul 01, 2009 at 12:50:32PM -0400, David Huff wrote: > Anyone see any issues with libguestfs and yum working weirdly?? > > If I mount an disk image with guestfish and try to install new packages > with yum, it gives rpmdb errors. However if I "launch" the disk images > as a guest in a fill virt container like qemu, there are no rpmdb error > and I can install new packages with yum.... > > Also, if I remove the rpmdb and rebuild via guestfish, then yum seems to > be working fine.... > > command "rm -f /var/lib/rpm/__db.004" > command "rpm --rebuilddb" > > Then yum seems to work: > > command "yum install vim-enhanced" > > It looks like yum is still using something outside of guestfish, anyone > have any comments/ideas on this?? Strange one. I can tell you that yum cannot be using anything 'outside' the appliance. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From mbooth at redhat.com Wed Jul 1 17:19:13 2009 From: mbooth at redhat.com (Matthew Booth) Date: Wed, 01 Jul 2009 18:19:13 +0100 Subject: [fedora-virt] [PATCH] Remove receive callbacks (libguestfs) Message-ID: <4A4B9A91.2030301@redhat.com> From commit message: ======== This patch fixes a class of race conditions characterised by the following sequence of events: LIBRARY DAEMON send download request receive download request respond with download response start sending file chunks set reply callback to 'download' run main loop At this stage the download reply callback receives both the download reply and some file chunks. The current architecture doesn't provide a clean way to prevent this from happening. This patch fixes the above problem by changing the socket receive handler to do nothing but buffering, and provides 2 new apis: guestfs_get_reply guestfs_free_reply These will always de-queue exactly 1 message, which is always what is wanted. ======= This is a fairly invasive patch. Note that it still uses the main loop for reading and writing data to the socket. The patch also looks a lot bigger than it really is, because it changes the auto-generated code. I'm separately planning to remove auto-generated code from git. Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-Remove-receive-callbacks.patch URL: From mbooth at redhat.com Wed Jul 1 17:23:14 2009 From: mbooth at redhat.com (Matthew Booth) Date: Wed, 01 Jul 2009 18:23:14 +0100 Subject: [fedora-virt] libguestfs tests running much slower Message-ID: <4A4B9B82.1010506@redhat.com> This is only subjective, and could yet be something entirely random on my machine. However, I just pulled changes 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 times slower. Is it just me? Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 From jim at meyering.net Wed Jul 1 17:31:12 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 19:31:12 +0200 Subject: [fedora-virt] [PATCH] add comments suggesting memory-handling improvements In-Reply-To: <87hbxwz6pt.fsf@meyering.net> (Jim Meyering's message of "Wed, 01 Jul 2009 18:52:14 +0200") References: <87skhg1oih.fsf@meyering.net> <20090701144908.GA16409@amd.home.annexia.org> <87ws6sz85q.fsf@meyering.net> <20090701163224.GF14689@amd.home.annexia.org> <20090701164109.GA17323@amd.home.annexia.org> <87hbxwz6pt.fsf@meyering.net> Message-ID: <87ab3oz4wv.fsf@meyering.net> Jim Meyering wrote: > Richard W.M. Jones wrote: >> On Wed, Jul 01, 2009 at 05:32:24PM +0100, Richard W.M. Jones wrote: >>> On Wed, Jul 01, 2009 at 06:21:05PM +0200, Jim Meyering wrote: >>> > 16/174 test_head_n_1 >>> > mount: /dev/vda1 on /: mount: wrong fs type, bad option, bad superblock on /dev/vda1, >>> > missing codepage or helper program, or other error >>> > In some cases useful info is found in syslog - try >>> > dmesg | tail or so >>> > test_head_n_1 FAILED >>> > ... >>> > 25/174 test_glob_expand_0 >>> > mount: /dev/vda1 on /: mount: unknown filesystem type 'lvm2pv' >>> > test_glob_expand_0 FAILED >>> >>> Yes, sorry, I just broke the test suite. Fix coming up >>> as soon as I know it passes 'make check' ... >> >> Do you want to try it again now, with the latest from git. > > Rebased and running the tests... > 31/174 and counting. All tests passed, so I pushed. From jim at meyering.net Wed Jul 1 17:39:13 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 19:39:13 +0200 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <4A4B9B82.1010506@redhat.com> (Matthew Booth's message of "Wed, 01 Jul 2009 18:23:14 +0100") References: <4A4B9B82.1010506@redhat.com> Message-ID: <874otwz4ji.fsf@meyering.net> Matthew Booth wrote: > This is only subjective, and could yet be something entirely random on > my machine. However, I just pulled changes > 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe > and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 > times slower. Is it just me? Hi Matt, I've noticed that some programs (thinking of one of augeas' self tests, in particular) can take far longer when there is limited memory than when they don't hit the limit. For example, one "make check" test takes just 5 seconds most of the time, but occasionally it takes 30s on an idle system. strace -c showed that in that case, most of the time was spent in the many sbrk syscalls. From jim at meyering.net Wed Jul 1 18:16:16 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 20:16:16 +0200 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <4A4B9B82.1010506@redhat.com> (Matthew Booth's message of "Wed, 01 Jul 2009 18:23:14 +0100") References: <4A4B9B82.1010506@redhat.com> Message-ID: <87vdmcxo9b.fsf@meyering.net> Matthew Booth wrote: > This is only subjective, and could yet be something entirely random on > my machine. However, I just pulled changes > 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe > and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 > times slower. Is it just me? Hi Matt, It's not just you. I've confirmed it. I reset back to 202e11543ead0d21a8485879654c927ec95ea7f0 [Don't dereference or free undefined "msg" upon OOM.], ran make, then "make check" and the latter took 15 minutes. Now, "make check" on the latest, f20854ec61eef1aea313920f0cf193a78c1a9219 [fish: handle some out-of-memory conditions], is at only 95/174, and it's already taken 23 minutes (50% longer). I noticed that this one 35/174 test_zerofree_0 took a particularly long time, but wasn't watching the whole time, so no hard numbers. From jim at meyering.net Wed Jul 1 19:42:37 2009 From: jim at meyering.net (Jim Meyering) Date: Wed, 01 Jul 2009 21:42:37 +0200 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <87vdmcxo9b.fsf@meyering.net> (Jim Meyering's message of "Wed, 01 Jul 2009 20:16:16 +0200") References: <4A4B9B82.1010506@redhat.com> <87vdmcxo9b.fsf@meyering.net> Message-ID: <87prckxk9e.fsf@meyering.net> Jim Meyering wrote: > Matthew Booth wrote: >> This is only subjective, and could yet be something entirely random on >> my machine. However, I just pulled changes >> 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe >> and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 >> times slower. Is it just me? > > Hi Matt, > > It's not just you. I've confirmed it. > > I reset back to 202e11543ead0d21a8485879654c927ec95ea7f0 > [Don't dereference or free undefined "msg" upon OOM.], > ran make, then "make check" and the latter took 15 minutes. > > Now, "make check" on the latest, f20854ec61eef1aea313920f0cf193a78c1a9219 > [fish: handle some out-of-memory conditions], is at only 95/174, and it's > already taken 23 minutes (50% longer). I noticed that this one > > 35/174 test_zerofree_0 > > took a particularly long time, but wasn't watching the whole time, > so no hard numbers. It finished. elapsed time: 33 minutes. Over double the time from 6 commits ago. Ironically, the commit that appears to introduce this slow-down talks about improved performance: Change to use virtio_blk (virtio block device) by default virtio_blk is the fast, virt-native block device driver supported by qemu and KVM. Note that virtio_blk device names are called /dev/vd*. Existing scripts should continue working because device name translation will silently change device names of the form /dev/sd* to /dev/vd* as required. See also: http://libguestfs.org/guestfs.3.html#block_device_naming I did git rebase -i HEAD~7 and deleted the line for that commit, rebuilt, and then "make check" took nearly 15 minutes again. However, there were failures: /sbin/sfdisk /dev/sda: external command failed test_umount_all_1 FAILED /sbin/sfdisk /dev/sda: external command failed test_lvcreate_0 FAILED /sbin/sfdisk /dev/sda: external command failed test_vgcreate_0 FAILED /sbin/sfdisk /dev/sda: external command failed test_pvcreate_0 FAILED /sbin/sfdisk /dev/sda: external command failed test_lvs_1 FAILED /sbin/sfdisk /dev/sda: external command failed test_vgs_1 FAILED /sbin/sfdisk /dev/sda: external command failed test_pvs_1 FAILED /sbin/sfdisk /dev/sda: external command failed test_list_partitions_1 FAILED ***** 8 / 174 tests FAILED ***** From agx at sigxcpu.org Wed Jul 1 20:19:41 2009 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Wed, 1 Jul 2009 22:19:41 +0200 Subject: [fedora-virt] Re: [PATCH] Change libguestfs to use virtio block devices In-Reply-To: <20090630145123.GA7792@amd.home.annexia.org> References: <20090630145123.GA7792@amd.home.annexia.org> Message-ID: <20090701201941.GB14567@bogon.sigxcpu.org> On Tue, Jun 30, 2009 at 03:51:23PM +0100, Richard W.M. Jones wrote: > The following set of patches changes libguestfs to use virtio block > devices by default. Looks good to me. -- Guido From rich at lat.com Wed Jul 1 20:52:44 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 01 Jul 2009 16:52:44 -0400 Subject: [fedora-virt] libvirtd log file location Message-ID: <200907012052.n61Kqips000992@raspberry.lat.com> With the various testing I am trying I managed to get myself into a bad situation. The libvirtd daemon won't stay up, and I don't see a log file in the places I've look for it at. Current situation is this: 'service libvirtd start' appears to work okay 'service libvirtd status' says 'libvirtd dead but pid file exists' I'll reboot in a bit, but I wanted to check the log file first--if I can find it. Rich From dlbewley at lib.ucdavis.edu Wed Jul 1 23:41:54 2009 From: dlbewley at lib.ucdavis.edu (Dale Bewley) Date: Wed, 01 Jul 2009 16:41:54 -0700 Subject: [fedora-virt] libvirtd log file location In-Reply-To: <200907012052.n61Kqips000992@raspberry.lat.com> References: <200907012052.n61Kqips000992@raspberry.lat.com> Message-ID: <1246491714.23295.10.camel@tofu.lib.ucdavis.edu> On Wed, 2009-07-01 at 16:52 -0400, Rich Mahn wrote: > With the various testing I am trying I managed to get myself into > a bad situation. The libvirtd daemon won't stay up, and I don't > see a log file in the places I've look for it at. > > Current situation is this: > > 'service libvirtd start' appears to work okay > 'service libvirtd status' says 'libvirtd dead but pid file exists' > > I'll reboot in a bit, but I wanted to check the log file first--if > I can find it. For tips on finding relevant logs and turning up debugging see http://fedoraproject.org/wiki/Reporting_virtualization_bugs -- Dale Bewley - Unix Administrator - Shields Library - UC Davis GPG: 0xB098A0F3 0D5A 9AEB 43F4 F84C 7EFD 1753 064D 2583 B098 A0F3 From rjones at redhat.com Thu Jul 2 10:07:47 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 11:07:47 +0100 Subject: [fedora-virt] [PATCH] Remove receive callbacks (libguestfs) In-Reply-To: <4A4B9A91.2030301@redhat.com> References: <4A4B9A91.2030301@redhat.com> Message-ID: <20090702100747.GA22604@amd.home.annexia.org> On Wed, Jul 01, 2009 at 06:19:13PM +0100, Matthew Booth wrote: > From commit message: > ======== > This patch fixes a class of race conditions characterised by the > following sequence of events: > > LIBRARY DAEMON > send download request > receive download request > respond with download response > start sending file chunks > set reply callback to 'download' > run main loop > > At this stage the download reply callback receives both the download > reply and some file chunks. The current architecture doesn't provide a > clean way > to prevent this from happening. > > This patch fixes the above problem by changing the socket receive > handler to do nothing but buffering, and provides 2 new apis: > > guestfs_get_reply > guestfs_free_reply > > These will always de-queue exactly 1 message, which is always what is > wanted. > ======= > > This is a fairly invasive patch. Note that it still uses the main loop > for reading and writing data to the socket. > > The patch also looks a lot bigger than it really is, because it changes > the auto-generated code. I'm separately planning to remove > auto-generated code from git. > > Matt > -- > Matthew Booth, RHCA, RHCSS > Red Hat Engineering, Virtualisation Team > > M: +44 (0)7977 267231 > GPG ID: D33C3490 > GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 > >From 2e155ead570e8aba98d8763cebaa50cfa8a73da6 Mon Sep 17 00:00:00 2001 > From: Matthew Booth > Date: Sat, 27 Jun 2009 22:05:48 +0100 > Subject: [PATCH] Remove receive callbacks > > This patch fixes a class of race conditions characterised by the > following sequence of events: > > LIBRARY DAEMON > send download request > receive download request > respond with download response > start sending file chunks > set reply callback to 'download' > run main loop > > At this stage the download reply callback receives both the download > reply and some file chunks. The current architecture doesn't provide a clean way > to prevent this from happening. > > This patch fixes the above problem by changing the socket receive > handler to do nothing but buffering, and provides 2 new apis: > > guestfs_get_reply > guestfs_free_reply > > These will always de-queue exactly 1 message, which is always what is > wanted. > --- > src/generator.ml | 207 +- > src/guestfs-actions.c |15436 +++++++++++++++++++++++-------------------------- > src/guestfs.c | 668 +-- > src/guestfs.h | 13 +- > 4 files changed, 7510 insertions(+), 8814 deletions(-) > > diff --git a/src/generator.ml b/src/generator.ml > index 69fd706..c6e25ec 100755 > --- a/src/generator.ml > +++ b/src/generator.ml > @@ -3616,81 +3616,6 @@ check_state (guestfs_h *g, const char *caller) > List.iter ( > fun (shortname, style, _, _, _, _, _) -> > let name = "guestfs_" ^ shortname in > - > - (* Generate the context struct which stores the high-level > - * state between callback functions. > - *) > - pr "struct %s_ctx {\n" shortname; > - pr " /* This flag is set by the callbacks, so we know we've done\n"; > - pr " * the callbacks as expected, and in the right sequence.\n"; > - pr " * 0 = not called, 1 = reply_cb called.\n"; > - pr " */\n"; > - pr " int cb_sequence;\n"; > - pr " struct guestfs_message_header hdr;\n"; > - pr " struct guestfs_message_error err;\n"; > - (match fst style with > - | RErr -> () > - | RConstString _ -> > - failwithf "RConstString cannot be returned from a daemon function" > - | RInt _ | RInt64 _ > - | RBool _ | RString _ | RStringList _ > - | RIntBool _ > - | RPVList _ | RVGList _ | RLVList _ > - | RStat _ | RStatVFS _ > - | RHashtable _ -> You'll get some conflicts when you rebase, because I added another case (RDirentList). > - pr " struct %s_ret ret;\n" name > - ); > - pr "};\n"; > - pr "\n"; > - > - (* Generate the reply callback function. *) > - pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname; > - pr "{\n"; > - pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; > - pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname; > - pr "\n"; > - pr " /* This should definitely not happen. */\n"; > - pr " if (ctx->cb_sequence != 0) {\n"; > - pr " ctx->cb_sequence = 9999;\n"; > - pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - pr "\n"; > - pr " ml->main_loop_quit (ml, g);\n"; > - pr "\n"; > - pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n"; > - pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n"; > - pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n"; > - pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n" > - name; > - pr " return;\n"; > - pr " }\n"; > - pr " goto done;\n"; > - pr " }\n"; > - > - (match fst style with > - | RErr -> () > - | RConstString _ -> > - failwithf "RConstString cannot be returned from a daemon function" > - | RInt _ | RInt64 _ > - | RBool _ | RString _ | RStringList _ > - | RIntBool _ > - | RPVList _ | RVGList _ | RLVList _ > - | RStat _ | RStatVFS _ > - | RHashtable _ -> > - pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name; > - pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - ); > - > - pr " done:\n"; > - pr " ctx->cb_sequence = 1;\n"; > - pr "}\n\n"; > - > (* Generate the action stub. *) > generate_prototype ~extern:false ~semicolon:false ~newline:true > ~handle:"g" name style; > @@ -3713,15 +3638,26 @@ check_state (guestfs_h *g, const char *caller) > | _ -> pr " struct %s_args args;\n" name > ); > > - pr " struct %s_ctx ctx;\n" shortname; > - pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; > + pr " struct guestfs_message_header hdr = {};\n"; > + pr " struct guestfs_message_error err = {};\n"; > + (match fst style with > + | RErr -> () > + | RConstString _ -> > + failwithf "RConstString cannot be returned from a daemon function" > + | RInt _ | RInt64 _ > + | RBool _ | RString _ | RStringList _ > + | RIntBool _ > + | RPVList _ | RVGList _ | RLVList _ > + | RStat _ | RStatVFS _ > + | RHashtable _ -> > + pr " struct %s_ret ret = {};\n" name > + ); > + > pr " int serial;\n"; > pr "\n"; > pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code; > pr " guestfs_set_busy (g);\n"; > pr "\n"; > - pr " memset (&ctx, 0, sizeof ctx);\n"; > - pr "\n"; > > (* Send the main header and arguments. *) > (match snd style with > @@ -3756,7 +3692,6 @@ check_state (guestfs_h *g, const char *caller) > pr "\n"; > > (* Send any additional files (FileIn) requested. *) > - let need_read_reply_label = ref false in > List.iter ( > function > | FileIn n -> > @@ -3768,82 +3703,128 @@ check_state (guestfs_h *g, const char *caller) > pr " guestfs_end_busy (g);\n"; > pr " return %s;\n" error_code; > pr " }\n"; > - pr " if (r == -2) /* daemon cancelled */\n"; > - pr " goto read_reply;\n"; > - need_read_reply_label := true; > pr " }\n"; > pr "\n"; > | _ -> () > ) (snd style); > > (* Wait for the reply from the remote end. *) > - if !need_read_reply_label then pr " read_reply:\n"; > - pr " guestfs__switch_to_receiving (g);\n"; > - pr " ctx.cb_sequence = 0;\n"; > - pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname; > - pr " (void) ml->main_loop_run (ml, g);\n"; > - pr " guestfs_set_reply_callback (g, NULL, NULL);\n"; > - pr " if (ctx.cb_sequence != 1) {\n"; > - pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " guestfs_reply_t reply;\n"; > + pr "\n"; > + pr " for (;;) {\n"; > + pr " guestfs_get_reply (g, &reply, 1);\n"; > + pr "\n"; > + pr " if (GUESTFS_CANCEL_FLAG == reply.len) {\n"; > + pr " /* This message was delayed from a previous file transaction. */\n"; > + pr " continue;\n"; > + pr " }\n"; > + pr "\n"; > + pr " if (GUESTFS_LAUNCH_FLAG == reply.len) {\n"; > + pr " error (g, \"%%s reply failed, received unexpected launch message\",\n"; > + pr " \"%s\");\n" name; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + pr " }\n"; > + pr "\n"; > + pr " if (0 == reply.len) {\n"; > + pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + pr " }\n"; > + pr "\n"; > + pr " break;\n"; > pr " }\n"; > pr "\n"; > > - pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n" > + pr " if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) {\n"; > + pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + pr "\n"; > + pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n"; > + pr " if (!xdr_guestfs_message_error (&reply.xdr, &err)) {\n"; > + pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n" > + name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + pr " }\n"; > + > + (match fst style with > + | RErr -> () > + | RConstString _ -> > + failwithf "RConstString cannot be returned from a daemon function" > + | RInt _ | RInt64 _ > + | RBool _ | RString _ | RStringList _ > + | RIntBool _ > + | RPVList _ | RVGList _ | RLVList _ > + | RStat _ | RStatVFS _ > + | RHashtable _ -> > + pr " else if (!xdr_%s_ret (&reply.xdr, &ret)) {\n" name; > + pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + ); > + > + pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n" > (String.uppercase shortname); > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " goto recv_error;\n"; > pr " }\n"; > pr "\n"; > > - pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n"; > - pr " error (g, \"%%s\", ctx.err.error_message);\n"; > - pr " free (ctx.err.error_message);\n"; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n"; > + pr " error (g, \"%%s\", err.error_message);\n"; > + pr " free (err.error_message);\n"; > + pr " goto recv_error;\n"; > pr " }\n"; > pr "\n"; > > + pr " guestfs_free_reply (g, &reply);\n\n"; > + > (* Expecting to receive further files (FileOut)? *) > List.iter ( > function > | FileOut n -> > pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > pr " }\n"; > pr "\n"; > | _ -> () > ) (snd style); > > - pr " guestfs_end_busy (g);\n"; > + pr " guestfs_end_busy (g);\n\n"; > > (match fst style with > | RErr -> pr " return 0;\n" > | RInt n | RInt64 n | RBool n -> > - pr " return ctx.ret.%s;\n" n > + pr " return ret.%s;\n" n > | RConstString _ -> > failwithf "RConstString cannot be returned from a daemon function" > | RString n -> > - pr " return ctx.ret.%s; /* caller will free */\n" n > + pr " return ret.%s; /* caller will free */\n" n > | RStringList n | RHashtable n -> > pr " /* caller will free this, but we need to add a NULL entry */\n"; > - pr " ctx.ret.%s.%s_val =\n" n n; > - pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n; > - pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n" > + pr " ret.%s.%s_val =\n" n n; > + pr " safe_realloc (g, ret.%s.%s_val,\n" n n; > + pr " sizeof (char *) * (ret.%s.%s_len + 1));\n" > n n; > - pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n; > - pr " return ctx.ret.%s.%s_val;\n" n n > + pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n; > + pr " return ret.%s.%s_val;\n" n n > | RIntBool _ -> > pr " /* caller with free this */\n"; > - pr " return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));\n" > + pr " return safe_memdup (g, &ret, sizeof (ret));\n" > | RPVList n | RVGList n | RLVList n > | RStat n | RStatVFS n -> > pr " /* caller will free this */\n"; > - pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n > + pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n > ); > > + pr "\n"; > + pr " recv_error:\n"; > + pr " guestfs_free_reply (g, &reply);\n"; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + > pr "}\n\n" > ) daemon_functions > > diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c > index a46b339..8df6170 100644 > --- a/src/guestfs-actions.c > +++ b/src/guestfs-actions.c > @@ -83,59 +83,18 @@ check_state (guestfs_h *g, const char *caller) > return 0; > } > > -struct mount_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > - > -static void mount_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mount_ctx *ctx = (struct mount_ctx *) data; > - > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mount"); > - return; > - } > - > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mount"); > - return; > - } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mount"); > - return; > - } > - goto done; > - } > - done: > - ctx->cb_sequence = 1; > -} > - > int guestfs_mount (guestfs_h *g, > const char *device, > const char *mountpoint) > { > struct guestfs_mount_args args; > - struct mount_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mount") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.mountpoint = (char *) mountpoint; > serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT, > @@ -145,168 +104,150 @@ int guestfs_mount (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mount_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mount"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sync_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mount"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sync_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sync_ctx *ctx = (struct sync_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mount"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sync"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sync"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mount"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sync"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mount"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_sync (guestfs_h *g) > { > - struct sync_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_sync") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_SYNC, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sync_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sync"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SYNC, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct touch_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sync"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void touch_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct touch_ctx *ctx = (struct touch_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sync"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_touch"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_touch"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sync"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_touch"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sync"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SYNC, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_touch (guestfs_h *g, > const char *path) > { > struct guestfs_touch_args args; > - struct touch_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_touch") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_TOUCH, > (xdrproc_t) xdr_guestfs_touch_args, (char *) &args); > @@ -315,90 +256,77 @@ int guestfs_touch (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, touch_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_touch"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TOUCH, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct cat_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_cat_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_touch"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void cat_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct cat_ctx *ctx = (struct cat_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_touch"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_cat"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_cat"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_touch"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_cat"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_touch"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_cat_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_cat"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TOUCH, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_cat (guestfs_h *g, > const char *path) > { > struct guestfs_cat_args args; > - struct cat_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_cat_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_cat") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_CAT, > (xdrproc_t) xdr_guestfs_cat_args, (char *) &args); > @@ -407,90 +335,81 @@ char *guestfs_cat (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, cat_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_cat"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CAT, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.content; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct ll_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_ll_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_cat"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void ll_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct ll_ctx *ctx = (struct ll_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_cat"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_ll"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_ll"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_cat"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_ll"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_cat"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_ll_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_ll"); > - return; > + else if (!xdr_guestfs_cat_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_cat"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CAT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.content; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_ll (guestfs_h *g, > const char *directory) > { > struct guestfs_ll_args args; > - struct ll_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_ll_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_ll") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_LL, > (xdrproc_t) xdr_guestfs_ll_args, (char *) &args); > @@ -499,90 +418,81 @@ char *guestfs_ll (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, ll_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_ll"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.listing; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct ls_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_ls_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_ll"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void ls_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct ls_ctx *ctx = (struct ls_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_ll"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_ls"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_ls"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_ll"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_ls"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_ll"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_ls_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_ls"); > - return; > + else if (!xdr_guestfs_ll_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_ll"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.listing; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_ls (guestfs_h *g, > const char *directory) > { > struct guestfs_ls_args args; > - struct ls_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_ls_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_ls") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_LS, > (xdrproc_t) xdr_guestfs_ls_args, (char *) &args); > @@ -591,827 +501,746 @@ char **guestfs_ls (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, ls_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_ls"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.listing.listing_val = > - safe_realloc (g, ctx.ret.listing.listing_val, > - sizeof (char *) * (ctx.ret.listing.listing_len + 1)); > - ctx.ret.listing.listing_val[ctx.ret.listing.listing_len] = NULL; > - return ctx.ret.listing.listing_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct list_devices_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_list_devices_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_ls"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void list_devices_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct list_devices_ctx *ctx = (struct list_devices_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_ls"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_list_devices"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_list_devices"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_ls"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_list_devices"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_ls"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_list_devices_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_list_devices"); > - return; > + else if (!xdr_guestfs_ls_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_ls"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.listing.listing_val = > + safe_realloc (g, ret.listing.listing_val, > + sizeof (char *) * (ret.listing.listing_len + 1)); > + ret.listing.listing_val[ret.listing.listing_len] = NULL; > + return ret.listing.listing_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_list_devices (guestfs_h *g) > { > - struct list_devices_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_list_devices_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_list_devices") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_DEVICES, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, list_devices_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.devices.devices_val = > - safe_realloc (g, ctx.ret.devices.devices_val, > - sizeof (char *) * (ctx.ret.devices.devices_len + 1)); > - ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL; > - return ctx.ret.devices.devices_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct list_partitions_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_list_partitions_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_list_devices"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void list_partitions_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct list_partitions_ctx *ctx = (struct list_partitions_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_list_devices"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_list_partitions"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_list_partitions"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_list_devices"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_list_partitions"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_list_devices"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_list_partitions_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_list_partitions"); > - return; > + else if (!xdr_guestfs_list_devices_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_list_devices"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LIST_DEVICES, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.devices.devices_val = > + safe_realloc (g, ret.devices.devices_val, > + sizeof (char *) * (ret.devices.devices_len + 1)); > + ret.devices.devices_val[ret.devices.devices_len] = NULL; > + return ret.devices.devices_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_list_partitions (guestfs_h *g) > { > - struct list_partitions_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_list_partitions_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_list_partitions") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_LIST_PARTITIONS, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, list_partitions_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.partitions.partitions_val = > - safe_realloc (g, ctx.ret.partitions.partitions_val, > - sizeof (char *) * (ctx.ret.partitions.partitions_len + 1)); > - ctx.ret.partitions.partitions_val[ctx.ret.partitions.partitions_len] = NULL; > - return ctx.ret.partitions.partitions_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct pvs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_pvs_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_list_partitions"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void pvs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct pvs_ctx *ctx = (struct pvs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_list_partitions"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_pvs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_pvs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_list_partitions"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_pvs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_list_partitions"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_pvs_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_pvs"); > - return; > + else if (!xdr_guestfs_list_partitions_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_list_partitions"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LIST_PARTITIONS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.partitions.partitions_val = > + safe_realloc (g, ret.partitions.partitions_val, > + sizeof (char *) * (ret.partitions.partitions_len + 1)); > + ret.partitions.partitions_val[ret.partitions.partitions_len] = NULL; > + return ret.partitions.partitions_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_pvs (guestfs_h *g) > { > - struct pvs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_pvs_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_pvs") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_PVS, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, pvs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_pvs"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.physvols.physvols_val = > - safe_realloc (g, ctx.ret.physvols.physvols_val, > - sizeof (char *) * (ctx.ret.physvols.physvols_len + 1)); > - ctx.ret.physvols.physvols_val[ctx.ret.physvols.physvols_len] = NULL; > - return ctx.ret.physvols.physvols_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vgs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_vgs_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_pvs"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void vgs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vgs_ctx *ctx = (struct vgs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_pvs"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vgs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vgs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_pvs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vgs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_pvs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_vgs_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_vgs"); > - return; > + else if (!xdr_guestfs_pvs_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_pvs"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PVS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.physvols.physvols_val = > + safe_realloc (g, ret.physvols.physvols_val, > + sizeof (char *) * (ret.physvols.physvols_len + 1)); > + ret.physvols.physvols_val[ret.physvols.physvols_len] = NULL; > + return ret.physvols.physvols_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_vgs (guestfs_h *g) > { > - struct vgs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_vgs_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_vgs") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_VGS, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vgs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vgs"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.volgroups.volgroups_val = > - safe_realloc (g, ctx.ret.volgroups.volgroups_val, > - sizeof (char *) * (ctx.ret.volgroups.volgroups_len + 1)); > - ctx.ret.volgroups.volgroups_val[ctx.ret.volgroups.volgroups_len] = NULL; > - return ctx.ret.volgroups.volgroups_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_lvs_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vgs"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void lvs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvs_ctx *ctx = (struct lvs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vgs"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vgs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vgs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_lvs_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_lvs"); > - return; > + else if (!xdr_guestfs_vgs_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_vgs"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VGS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.volgroups.volgroups_val = > + safe_realloc (g, ret.volgroups.volgroups_val, > + sizeof (char *) * (ret.volgroups.volgroups_len + 1)); > + ret.volgroups.volgroups_val[ret.volgroups.volgroups_len] = NULL; > + return ret.volgroups.volgroups_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_lvs (guestfs_h *g) > { > - struct lvs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_lvs_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_lvs") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_LVS, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvs"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.logvols.logvols_val = > - safe_realloc (g, ctx.ret.logvols.logvols_val, > - sizeof (char *) * (ctx.ret.logvols.logvols_len + 1)); > - ctx.ret.logvols.logvols_val[ctx.ret.logvols.logvols_len] = NULL; > - return ctx.ret.logvols.logvols_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct pvs_full_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_pvs_full_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvs"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void pvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct pvs_full_ctx *ctx = (struct pvs_full_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvs"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_pvs_full"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_pvs_full"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_pvs_full"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_pvs_full_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_pvs_full"); > - return; > + else if (!xdr_guestfs_lvs_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_lvs"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.logvols.logvols_val = > + safe_realloc (g, ret.logvols.logvols_val, > + sizeof (char *) * (ret.logvols.logvols_len + 1)); > + ret.logvols.logvols_val[ret.logvols.logvols_len] = NULL; > + return ret.logvols.logvols_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_lvm_pv_list *guestfs_pvs_full (guestfs_h *g) > { > - struct pvs_full_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_pvs_full_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_pvs_full") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_PVS_FULL, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, pvs_full_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVS_FULL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.physvols, sizeof (ctx.ret.physvols)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vgs_full_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_vgs_full_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_pvs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void vgs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vgs_full_ctx *ctx = (struct vgs_full_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_pvs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vgs_full"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vgs_full"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_pvs_full"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vgs_full"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_pvs_full"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_vgs_full_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_vgs_full"); > - return; > + else if (!xdr_guestfs_pvs_full_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_pvs_full"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PVS_FULL, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.physvols, sizeof (ret.physvols)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_lvm_vg_list *guestfs_vgs_full (guestfs_h *g) > { > - struct vgs_full_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_vgs_full_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_vgs_full") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_VGS_FULL, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vgs_full_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGS_FULL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.volgroups, sizeof (ctx.ret.volgroups)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvs_full_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_lvs_full_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vgs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void lvs_full_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvs_full_ctx *ctx = (struct lvs_full_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vgs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvs_full"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvs_full"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vgs_full"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvs_full"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vgs_full"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_lvs_full_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_lvs_full"); > - return; > + else if (!xdr_guestfs_vgs_full_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_vgs_full"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VGS_FULL, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.volgroups, sizeof (ret.volgroups)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_lvm_lv_list *guestfs_lvs_full (guestfs_h *g) > { > - struct lvs_full_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_lvs_full_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_lvs_full") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_LVS_FULL, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvs_full_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVS_FULL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.logvols, sizeof (ctx.ret.logvols)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct read_lines_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_read_lines_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void read_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct read_lines_ctx *ctx = (struct read_lines_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvs_full"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_read_lines"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_read_lines"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvs_full"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_read_lines"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvs_full"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_read_lines_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_read_lines"); > - return; > + else if (!xdr_guestfs_lvs_full_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_lvs_full"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVS_FULL, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.logvols, sizeof (ret.logvols)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_read_lines (guestfs_h *g, > const char *path) > { > struct guestfs_read_lines_args args; > - struct read_lines_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_read_lines_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_read_lines") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_READ_LINES, > (xdrproc_t) xdr_guestfs_read_lines_args, (char *) &args); > @@ -1420,75 +1249,72 @@ char **guestfs_read_lines (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, read_lines_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_READ_LINES, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_init_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_read_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void aug_init_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_init_ctx *ctx = (struct aug_init_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_read_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_init"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_init"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_read_lines"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_init"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_read_lines"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_read_lines_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_read_lines"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_READ_LINES, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_aug_init (guestfs_h *g, > @@ -1496,15 +1322,13 @@ int guestfs_aug_init (guestfs_h *g, > int flags) > { > struct guestfs_aug_init_args args; > - struct aug_init_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_init") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.root = (char *) root; > args.flags = flags; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_INIT, > @@ -1514,158 +1338,137 @@ int guestfs_aug_init (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_init_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INIT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_close_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_init"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_close_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_close_ctx *ctx = (struct aug_close_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_init"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_close"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_close"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_init"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_close"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_init"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_INIT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_close (guestfs_h *g) > { > - struct aug_close_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_close") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_CLOSE, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_close_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_defvar_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_defvar_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_close"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_defvar_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_defvar_ctx *ctx = (struct aug_defvar_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_close"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defvar"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_defvar"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_close"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_defvar"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_close"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_defvar_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_defvar"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_CLOSE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_defvar (guestfs_h *g, > @@ -1673,15 +1476,14 @@ int guestfs_aug_defvar (guestfs_h *g, > const char *expr) > { > struct guestfs_aug_defvar_args args; > - struct aug_defvar_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_defvar_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_defvar") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.name = (char *) name; > args.expr = expr ? (char **) &expr : NULL; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_DEFVAR, > @@ -1691,75 +1493,67 @@ int guestfs_aug_defvar (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_defvar_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.nrnodes; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_defnode_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_defnode_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_defvar"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_defnode_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_defnode_ctx *ctx = (struct aug_defnode_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defvar"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_defnode"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_defnode"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_defvar"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_defnode"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_defvar"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_defnode_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_defnode"); > - return; > + else if (!xdr_guestfs_aug_defvar_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_defvar"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_DEFVAR, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.nrnodes; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g, > @@ -1768,15 +1562,14 @@ struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g, > const char *val) > { > struct guestfs_aug_defnode_args args; > - struct aug_defnode_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_defnode_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_defnode") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.name = (char *) name; > args.expr = (char *) expr; > args.val = (char *) val; > @@ -1787,91 +1580,82 @@ struct guestfs_int_bool *guestfs_aug_defnode (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_defnode_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller with free this */ > - return safe_memdup (g, &ctx.ret, sizeof (ctx.ret)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_get_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_get_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_defnode"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void aug_get_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_get_ctx *ctx = (struct aug_get_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_defnode"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_get"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_get"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_defnode"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_get"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_defnode"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_get_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_get"); > - return; > + else if (!xdr_guestfs_aug_defnode_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_defnode"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_DEFNODE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller with free this */ > + return safe_memdup (g, &ret, sizeof (ret)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_aug_get (guestfs_h *g, > const char *path) > { > struct guestfs_aug_get_args args; > - struct aug_get_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_get_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_get") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_GET, > (xdrproc_t) xdr_guestfs_aug_get_args, (char *) &args); > @@ -1880,70 +1664,67 @@ char *guestfs_aug_get (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_get_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_GET, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.val; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_set_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_get"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void aug_set_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_set_ctx *ctx = (struct aug_set_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_get"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_set"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_set"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_get"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_set"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_get"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_aug_get_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_get"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_GET, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.val; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_aug_set (guestfs_h *g, > @@ -1951,15 +1732,13 @@ int guestfs_aug_set (guestfs_h *g, > const char *val) > { > struct guestfs_aug_set_args args; > - struct aug_set_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_set") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > args.val = (char *) val; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SET, > @@ -1969,70 +1748,63 @@ int guestfs_aug_set (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_set_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SET, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_insert_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_set"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_insert_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_insert_ctx *ctx = (struct aug_insert_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_set"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_insert"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_insert"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_set"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_insert"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_set"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_SET, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_insert (guestfs_h *g, > @@ -2041,15 +1813,13 @@ int guestfs_aug_insert (guestfs_h *g, > int before) > { > struct guestfs_aug_insert_args args; > - struct aug_insert_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_insert") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > args.label = (char *) label; > args.before = before; > @@ -2060,90 +1830,77 @@ int guestfs_aug_insert (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_insert_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_rm_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_rm_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_insert"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_rm_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_rm_ctx *ctx = (struct aug_rm_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_insert"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_rm"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_rm"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_insert"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_rm"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_insert"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_rm_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_rm"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_INSERT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_rm (guestfs_h *g, > const char *path) > { > struct guestfs_aug_rm_args args; > - struct aug_rm_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_rm_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_rm") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_RM, > (xdrproc_t) xdr_guestfs_aug_rm_args, (char *) &args); > @@ -2152,70 +1909,67 @@ int guestfs_aug_rm (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_rm_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_RM, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.nrnodes; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_mv_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_rm"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_mv_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_mv_ctx *ctx = (struct aug_mv_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_rm"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_mv"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_mv"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_rm"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_mv"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_rm"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_aug_rm_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_rm"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_RM, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.nrnodes; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_mv (guestfs_h *g, > @@ -2223,15 +1977,13 @@ int guestfs_aug_mv (guestfs_h *g, > const char *dest) > { > struct guestfs_aug_mv_args args; > - struct aug_mv_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_mv") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.src = (char *) src; > args.dest = (char *) dest; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MV, > @@ -2241,90 +1993,77 @@ int guestfs_aug_mv (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_mv_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MV, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_match_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_match_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_mv"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_match_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_match_ctx *ctx = (struct aug_match_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_mv"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_match"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_match"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_mv"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_match"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_mv"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_match_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_match"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_MV, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_aug_match (guestfs_h *g, > const char *path) > { > struct guestfs_aug_match_args args; > - struct aug_match_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_match_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_match") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_MATCH, > (xdrproc_t) xdr_guestfs_aug_match_args, (char *) &args); > @@ -2333,261 +2072,234 @@ char **guestfs_aug_match (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_match_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.matches.matches_val = > - safe_realloc (g, ctx.ret.matches.matches_val, > - sizeof (char *) * (ctx.ret.matches.matches_len + 1)); > - ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL; > - return ctx.ret.matches.matches_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_save_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_match"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void aug_save_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_save_ctx *ctx = (struct aug_save_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_match"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_save"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_save"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_match"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_save"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_match"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_aug_match_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_match"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_MATCH, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.matches.matches_val = > + safe_realloc (g, ret.matches.matches_val, > + sizeof (char *) * (ret.matches.matches_len + 1)); > + ret.matches.matches_val[ret.matches.matches_len] = NULL; > + return ret.matches.matches_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_aug_save (guestfs_h *g) > { > - struct aug_save_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_save") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_SAVE, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_save_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_load_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_save"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_load_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_load_ctx *ctx = (struct aug_load_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_save"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_load"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_load"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_save"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_load"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_save"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_SAVE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_aug_load (guestfs_h *g) > { > - struct aug_load_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_aug_load") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LOAD, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_load_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct aug_ls_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_aug_ls_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_load"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void aug_ls_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct aug_ls_ctx *ctx = (struct aug_ls_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_load"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_aug_ls"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_aug_ls"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_load"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_aug_ls"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_load"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_aug_ls_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_aug_ls"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_LOAD, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_aug_ls (guestfs_h *g, > const char *path) > { > struct guestfs_aug_ls_args args; > - struct aug_ls_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_aug_ls_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_aug_ls") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_AUG_LS, > (xdrproc_t) xdr_guestfs_aug_ls_args, (char *) &args); > @@ -2596,90 +2308,85 @@ char **guestfs_aug_ls (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, aug_ls_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_AUG_LS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.matches.matches_val = > - safe_realloc (g, ctx.ret.matches.matches_val, > - sizeof (char *) * (ctx.ret.matches.matches_len + 1)); > - ctx.ret.matches.matches_val[ctx.ret.matches.matches_len] = NULL; > - return ctx.ret.matches.matches_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct rm_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_aug_ls"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void rm_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct rm_ctx *ctx = (struct rm_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_aug_ls"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_rm"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_rm"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_aug_ls"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_rm"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_aug_ls"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_aug_ls_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_aug_ls"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_AUG_LS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.matches.matches_val = > + safe_realloc (g, ret.matches.matches_val, > + sizeof (char *) * (ret.matches.matches_len + 1)); > + ret.matches.matches_val[ret.matches.matches_len] = NULL; > + return ret.matches.matches_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_rm (guestfs_h *g, > const char *path) > { > struct guestfs_rm_args args; > - struct rm_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_rm") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_RM, > (xdrproc_t) xdr_guestfs_rm_args, (char *) &args); > @@ -2688,85 +2395,76 @@ int guestfs_rm (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, rm_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_rm"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct rmdir_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_rm"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void rmdir_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct rmdir_ctx *ctx = (struct rmdir_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_rm"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_rmdir"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_rmdir"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_rm"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_rmdir"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_rm"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_RM, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_rmdir (guestfs_h *g, > const char *path) > { > struct guestfs_rmdir_args args; > - struct rmdir_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_rmdir") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_RMDIR, > (xdrproc_t) xdr_guestfs_rmdir_args, (char *) &args); > @@ -2775,85 +2473,76 @@ int guestfs_rmdir (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, rmdir_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RMDIR, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct rm_rf_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_rmdir"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void rm_rf_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct rm_rf_ctx *ctx = (struct rm_rf_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_rmdir"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_rm_rf"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_rm_rf"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_rmdir"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_rm_rf"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_rmdir"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_RMDIR, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_rm_rf (guestfs_h *g, > const char *path) > { > struct guestfs_rm_rf_args args; > - struct rm_rf_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_rm_rf") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_RM_RF, > (xdrproc_t) xdr_guestfs_rm_rf_args, (char *) &args); > @@ -2862,85 +2551,76 @@ int guestfs_rm_rf (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, rm_rf_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RM_RF, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkdir_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_rm_rf"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkdir_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkdir_ctx *ctx = (struct mkdir_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_rm_rf"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkdir"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_rm_rf"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkdir"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_rm_rf"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_RM_RF, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkdir (guestfs_h *g, > const char *path) > { > struct guestfs_mkdir_args args; > - struct mkdir_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkdir") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR, > (xdrproc_t) xdr_guestfs_mkdir_args, (char *) &args); > @@ -2949,85 +2629,76 @@ int guestfs_mkdir (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkdir_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkdir_p_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkdir"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkdir_p_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkdir_p_ctx *ctx = (struct mkdir_p_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkdir_p"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkdir_p"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkdir"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkdir_p"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkdir"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKDIR, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkdir_p (guestfs_h *g, > const char *path) > { > struct guestfs_mkdir_p_args args; > - struct mkdir_p_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkdir_p") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKDIR_P, > (xdrproc_t) xdr_guestfs_mkdir_p_args, (char *) &args); > @@ -3036,70 +2707,63 @@ int guestfs_mkdir_p (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkdir_p_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDIR_P, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct chmod_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkdir_p"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void chmod_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct chmod_ctx *ctx = (struct chmod_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkdir_p"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_chmod"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_chmod"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkdir_p"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_chmod"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkdir_p"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKDIR_P, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_chmod (guestfs_h *g, > @@ -3107,15 +2771,13 @@ int guestfs_chmod (guestfs_h *g, > const char *path) > { > struct guestfs_chmod_args args; > - struct chmod_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_chmod") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mode = mode; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_CHMOD, > @@ -3125,70 +2787,63 @@ int guestfs_chmod (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, chmod_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_chmod"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHMOD, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct chown_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_chmod"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void chown_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct chown_ctx *ctx = (struct chown_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_chmod"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_chown"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_chown"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_chmod"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_chown"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_chmod"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CHMOD, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_chown (guestfs_h *g, > @@ -3197,15 +2852,13 @@ int guestfs_chown (guestfs_h *g, > const char *path) > { > struct guestfs_chown_args args; > - struct chown_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_chown") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.owner = owner; > args.group = group; > args.path = (char *) path; > @@ -3216,90 +2869,77 @@ int guestfs_chown (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, chown_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_chown"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHOWN, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct exists_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_exists_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_chown"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void exists_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct exists_ctx *ctx = (struct exists_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_chown"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_exists"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_exists"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_chown"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_exists"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_chown"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_exists_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_exists"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CHOWN, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_exists (guestfs_h *g, > const char *path) > { > struct guestfs_exists_args args; > - struct exists_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_exists_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_exists") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_EXISTS, > (xdrproc_t) xdr_guestfs_exists_args, (char *) &args); > @@ -3308,90 +2948,81 @@ int guestfs_exists (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, exists_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_exists"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EXISTS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.existsflag; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct is_file_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_is_file_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_exists"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void is_file_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct is_file_ctx *ctx = (struct is_file_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_exists"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_is_file"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_is_file"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_exists"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_is_file"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_exists"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_is_file_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_is_file"); > - return; > + else if (!xdr_guestfs_exists_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_exists"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_EXISTS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.existsflag; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_is_file (guestfs_h *g, > const char *path) > { > struct guestfs_is_file_args args; > - struct is_file_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_is_file_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_is_file") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_IS_FILE, > (xdrproc_t) xdr_guestfs_is_file_args, (char *) &args); > @@ -3400,90 +3031,81 @@ int guestfs_is_file (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, is_file_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_is_file"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_FILE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.fileflag; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct is_dir_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_is_dir_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_is_file"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void is_dir_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct is_dir_ctx *ctx = (struct is_dir_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_is_file"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_is_dir"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_is_dir"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_is_file"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_is_dir"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_is_file"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_is_dir_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_is_dir"); > - return; > + else if (!xdr_guestfs_is_file_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_is_file"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_IS_FILE, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.fileflag; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_is_dir (guestfs_h *g, > const char *path) > { > struct guestfs_is_dir_args args; > - struct is_dir_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_is_dir_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_is_dir") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_IS_DIR, > (xdrproc_t) xdr_guestfs_is_dir_args, (char *) &args); > @@ -3492,85 +3114,80 @@ int guestfs_is_dir (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, is_dir_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_IS_DIR, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.dirflag; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct pvcreate_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_is_dir"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void pvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct pvcreate_ctx *ctx = (struct pvcreate_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_is_dir"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_pvcreate"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_pvcreate"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_is_dir"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_pvcreate"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_is_dir"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_is_dir_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_is_dir"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_IS_DIR, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.dirflag; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_pvcreate (guestfs_h *g, > const char *device) > { > struct guestfs_pvcreate_args args; > - struct pvcreate_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_pvcreate") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_PVCREATE, > (xdrproc_t) xdr_guestfs_pvcreate_args, (char *) &args); > @@ -3579,70 +3196,63 @@ int guestfs_pvcreate (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, pvcreate_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVCREATE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vgcreate_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_pvcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void vgcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vgcreate_ctx *ctx = (struct vgcreate_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_pvcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vgcreate"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vgcreate"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_pvcreate"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vgcreate"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_pvcreate"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PVCREATE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_vgcreate (guestfs_h *g, > @@ -3650,15 +3260,13 @@ int guestfs_vgcreate (guestfs_h *g, > char * const* const physvols) > { > struct guestfs_vgcreate_args args; > - struct vgcreate_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_vgcreate") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.volgroup = (char *) volgroup; > args.physvols.physvols_val = (char **) physvols; > for (args.physvols.physvols_len = 0; physvols[args.physvols.physvols_len]; args.physvols.physvols_len++) ; > @@ -3669,70 +3277,63 @@ int guestfs_vgcreate (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vgcreate_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGCREATE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvcreate_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vgcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void lvcreate_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvcreate_ctx *ctx = (struct lvcreate_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vgcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvcreate"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvcreate"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vgcreate"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvcreate"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vgcreate"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VGCREATE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_lvcreate (guestfs_h *g, > @@ -3741,15 +3342,13 @@ int guestfs_lvcreate (guestfs_h *g, > int mbytes) > { > struct guestfs_lvcreate_args args; > - struct lvcreate_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_lvcreate") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.logvol = (char *) logvol; > args.volgroup = (char *) volgroup; > args.mbytes = mbytes; > @@ -3760,70 +3359,63 @@ int guestfs_lvcreate (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvcreate_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVCREATE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkfs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkfs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkfs_ctx *ctx = (struct mkfs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvcreate"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkfs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkfs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvcreate"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkfs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvcreate"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVCREATE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkfs (guestfs_h *g, > @@ -3831,15 +3423,13 @@ int guestfs_mkfs (guestfs_h *g, > const char *device) > { > struct guestfs_mkfs_args args; > - struct mkfs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkfs") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.fstype = (char *) fstype; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKFS, > @@ -3849,70 +3439,63 @@ int guestfs_mkfs (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkfs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sfdisk_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkfs"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sfdisk_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sfdisk_ctx *ctx = (struct sfdisk_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkfs"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sfdisk"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkfs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sfdisk"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkfs"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKFS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_sfdisk (guestfs_h *g, > @@ -3923,15 +3506,13 @@ int guestfs_sfdisk (guestfs_h *g, > char * const* const lines) > { > struct guestfs_sfdisk_args args; > - struct sfdisk_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_sfdisk") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.cyls = cyls; > args.heads = heads; > @@ -3945,70 +3526,63 @@ int guestfs_sfdisk (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sfdisk_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct write_file_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sfdisk"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void write_file_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct write_file_ctx *ctx = (struct write_file_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_write_file"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_write_file"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sfdisk"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_write_file"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sfdisk"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SFDISK, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_write_file (guestfs_h *g, > @@ -4017,15 +3591,13 @@ int guestfs_write_file (guestfs_h *g, > int size) > { > struct guestfs_write_file_args args; > - struct write_file_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_write_file") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > args.content = (char *) content; > args.size = size; > @@ -4036,85 +3608,76 @@ int guestfs_write_file (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, write_file_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_write_file"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct umount_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_write_file"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void umount_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct umount_ctx *ctx = (struct umount_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_write_file"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_umount"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_umount"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_write_file"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_umount"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_write_file"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_WRITE_FILE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_umount (guestfs_h *g, > const char *pathordevice) > { > struct guestfs_umount_args args; > - struct umount_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_umount") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.pathordevice = (char *) pathordevice; > serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT, > (xdrproc_t) xdr_guestfs_umount_args, (char *) &args); > @@ -4123,349 +3686,309 @@ int guestfs_umount (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, umount_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_umount"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mounts_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_mounts_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_umount"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mounts_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mounts_ctx *ctx = (struct mounts_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_umount"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mounts"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mounts"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_umount"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mounts"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_umount"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_mounts_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_mounts"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_UMOUNT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_mounts (guestfs_h *g) > { > - struct mounts_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_mounts_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_mounts") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNTS, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mounts_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mounts"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNTS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.devices.devices_val = > - safe_realloc (g, ctx.ret.devices.devices_val, > - sizeof (char *) * (ctx.ret.devices.devices_len + 1)); > - ctx.ret.devices.devices_val[ctx.ret.devices.devices_len] = NULL; > - return ctx.ret.devices.devices_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct umount_all_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mounts"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void umount_all_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct umount_all_ctx *ctx = (struct umount_all_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mounts"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_umount_all"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_umount_all"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mounts"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_umount_all"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mounts"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_mounts_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_mounts"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNTS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.devices.devices_val = > + safe_realloc (g, ret.devices.devices_val, > + sizeof (char *) * (ret.devices.devices_len + 1)); > + ret.devices.devices_val[ret.devices.devices_len] = NULL; > + return ret.devices.devices_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_umount_all (guestfs_h *g) > { > - struct umount_all_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_umount_all") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_UMOUNT_ALL, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, umount_all_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvm_remove_all_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_umount_all"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void lvm_remove_all_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvm_remove_all_ctx *ctx = (struct lvm_remove_all_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_umount_all"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvm_remove_all"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_umount_all"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_umount_all"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_UMOUNT_ALL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_lvm_remove_all (guestfs_h *g) > { > - struct lvm_remove_all_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_lvm_remove_all") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_LVM_REMOVE_ALL, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvm_remove_all_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct file_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_file_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvm_remove_all"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void file_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct file_ctx *ctx = (struct file_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvm_remove_all"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_file"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_file"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvm_remove_all"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_file"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvm_remove_all"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_file_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_file"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVM_REMOVE_ALL, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_file (guestfs_h *g, > const char *path) > { > struct guestfs_file_args args; > - struct file_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_file_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_file") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_FILE, > (xdrproc_t) xdr_guestfs_file_args, (char *) &args); > @@ -4474,90 +3997,81 @@ char *guestfs_file (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, file_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_file"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FILE, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.description; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct command_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_command_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_file"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void command_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct command_ctx *ctx = (struct command_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_file"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_command"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_command"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_file"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_command"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_file"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_command_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_command"); > - return; > + else if (!xdr_guestfs_file_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_file"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_FILE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.description; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_command (guestfs_h *g, > char * const* const arguments) > { > struct guestfs_command_args args; > - struct command_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_command_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_command") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.arguments.arguments_val = (char **) arguments; > for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ; > serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND, > @@ -4567,90 +4081,81 @@ char *guestfs_command (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, command_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_command"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.output; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct command_lines_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_command_lines_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_command"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void command_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct command_lines_ctx *ctx = (struct command_lines_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_command"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_command_lines"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_command_lines"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_command"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_command_lines"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_command"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_command_lines_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_command_lines"); > - return; > + else if (!xdr_guestfs_command_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_command"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_COMMAND, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.output; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_command_lines (guestfs_h *g, > char * const* const arguments) > { > struct guestfs_command_lines_args args; > - struct command_lines_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_command_lines_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_command_lines") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.arguments.arguments_val = (char **) arguments; > for (args.arguments.arguments_len = 0; arguments[args.arguments.arguments_len]; args.arguments.arguments_len++) ; > serial = guestfs__send_sync (g, GUESTFS_PROC_COMMAND_LINES, > @@ -4660,95 +4165,86 @@ char **guestfs_command_lines (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, command_lines_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct stat_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_stat_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_command_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void stat_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct stat_ctx *ctx = (struct stat_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_command_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_stat"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_stat"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_command_lines"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_stat"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_command_lines"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_stat_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_stat"); > - return; > + else if (!xdr_guestfs_command_lines_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_command_lines"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_COMMAND_LINES, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_stat *guestfs_stat (guestfs_h *g, > const char *path) > { > struct guestfs_stat_args args; > - struct stat_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_stat_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_stat") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_STAT, > (xdrproc_t) xdr_guestfs_stat_args, (char *) &args); > @@ -4757,91 +4253,82 @@ struct guestfs_stat *guestfs_stat (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, stat_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_stat"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STAT, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lstat_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_lstat_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_stat"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void lstat_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lstat_ctx *ctx = (struct lstat_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_stat"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lstat"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lstat"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_stat"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lstat"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_stat"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_lstat_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_lstat"); > - return; > + else if (!xdr_guestfs_stat_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_stat"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_STAT, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.statbuf, sizeof (ret.statbuf)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_stat *guestfs_lstat (guestfs_h *g, > const char *path) > { > struct guestfs_lstat_args args; > - struct lstat_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_lstat_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_lstat") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_LSTAT, > (xdrproc_t) xdr_guestfs_lstat_args, (char *) &args); > @@ -4850,91 +4337,82 @@ struct guestfs_stat *guestfs_lstat (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lstat_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lstat"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LSTAT, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct statvfs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_statvfs_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lstat"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void statvfs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct statvfs_ctx *ctx = (struct statvfs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lstat"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_statvfs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_statvfs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lstat"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_statvfs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lstat"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_statvfs_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_statvfs"); > - return; > + else if (!xdr_guestfs_lstat_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_lstat"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LSTAT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.statbuf, sizeof (ret.statbuf)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g, > const char *path) > { > struct guestfs_statvfs_args args; > - struct statvfs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_statvfs_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_statvfs") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_STATVFS, > (xdrproc_t) xdr_guestfs_statvfs_args, (char *) &args); > @@ -4943,91 +4421,82 @@ struct guestfs_statvfs *guestfs_statvfs (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, statvfs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STATVFS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this */ > - return safe_memdup (g, &ctx.ret.statbuf, sizeof (ctx.ret.statbuf)); > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tune2fs_l_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_tune2fs_l_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_statvfs"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void tune2fs_l_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tune2fs_l_ctx *ctx = (struct tune2fs_l_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_statvfs"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tune2fs_l"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_statvfs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_statvfs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_tune2fs_l_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_tune2fs_l"); > - return; > + else if (!xdr_guestfs_statvfs_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_statvfs"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_STATVFS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this */ > + return safe_memdup (g, &ret.statbuf, sizeof (ret.statbuf)); > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_tune2fs_l (guestfs_h *g, > const char *device) > { > struct guestfs_tune2fs_l_args args; > - struct tune2fs_l_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_tune2fs_l_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_tune2fs_l") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_TUNE2FS_L, > (xdrproc_t) xdr_guestfs_tune2fs_l_args, (char *) &args); > @@ -5036,90 +4505,85 @@ char **guestfs_tune2fs_l (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tune2fs_l_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.superblock.superblock_val = > - safe_realloc (g, ctx.ret.superblock.superblock_val, > - sizeof (char *) * (ctx.ret.superblock.superblock_len + 1)); > - ctx.ret.superblock.superblock_val[ctx.ret.superblock.superblock_len] = NULL; > - return ctx.ret.superblock.superblock_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_setro_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tune2fs_l"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void blockdev_setro_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_setro_ctx *ctx = (struct blockdev_setro_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tune2fs_l"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setro"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tune2fs_l"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tune2fs_l"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_tune2fs_l_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_tune2fs_l"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TUNE2FS_L, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.superblock.superblock_val = > + safe_realloc (g, ret.superblock.superblock_val, > + sizeof (char *) * (ret.superblock.superblock_len + 1)); > + ret.superblock.superblock_val[ret.superblock.superblock_len] = NULL; > + return ret.superblock.superblock_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_blockdev_setro (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_setro_args args; > - struct blockdev_setro_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_setro") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRO, > (xdrproc_t) xdr_guestfs_blockdev_setro_args, (char *) &args); > @@ -5128,85 +4592,76 @@ int guestfs_blockdev_setro (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_setro_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_setrw_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_setro"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_setrw_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_setrw_ctx *ctx = (struct blockdev_setrw_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setro"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setrw"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_setro"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_setro"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_SETRO, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_setrw (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_setrw_args args; > - struct blockdev_setrw_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_setrw") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETRW, > (xdrproc_t) xdr_guestfs_blockdev_setrw_args, (char *) &args); > @@ -5215,90 +4670,77 @@ int guestfs_blockdev_setrw (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_setrw_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_getro_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_blockdev_getro_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_setrw"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_getro_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_getro_ctx *ctx = (struct blockdev_getro_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setrw"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getro"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_setrw"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_setrw"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_blockdev_getro_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_blockdev_getro"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_SETRW, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_getro (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_getro_args args; > - struct blockdev_getro_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_blockdev_getro_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_getro") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETRO, > (xdrproc_t) xdr_guestfs_blockdev_getro_args, (char *) &args); > @@ -5307,90 +4749,81 @@ int guestfs_blockdev_getro (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_getro_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.ro; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_getss_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_blockdev_getss_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_getro"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_getss_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_getss_ctx *ctx = (struct blockdev_getss_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getro"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getss"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_getro"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_getro"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_blockdev_getss_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_blockdev_getss"); > - return; > + else if (!xdr_guestfs_blockdev_getro_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_blockdev_getro"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_GETRO, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.ro; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_getss (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_getss_args args; > - struct blockdev_getss_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_blockdev_getss_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_getss") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSS, > (xdrproc_t) xdr_guestfs_blockdev_getss_args, (char *) &args); > @@ -5399,90 +4832,81 @@ int guestfs_blockdev_getss (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_getss_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.sectorsize; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_getbsz_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_blockdev_getbsz_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_getss"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_getbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_getbsz_ctx *ctx = (struct blockdev_getbsz_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getss"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getbsz"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_getss"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_getss"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_blockdev_getbsz_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz"); > - return; > + else if (!xdr_guestfs_blockdev_getss_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_blockdev_getss"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_GETSS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.sectorsize; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_getbsz (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_getbsz_args args; > - struct blockdev_getbsz_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_blockdev_getbsz_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_getbsz") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETBSZ, > (xdrproc_t) xdr_guestfs_blockdev_getbsz_args, (char *) &args); > @@ -5491,70 +4915,67 @@ int guestfs_blockdev_getbsz (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_getbsz_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.blocksize; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_setbsz_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_getbsz"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_setbsz_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_setbsz_ctx *ctx = (struct blockdev_setbsz_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getbsz"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_setbsz"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_getbsz"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_getbsz"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_blockdev_getbsz_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_blockdev_getbsz"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_GETBSZ, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.blocksize; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_setbsz (guestfs_h *g, > @@ -5562,15 +4983,13 @@ int guestfs_blockdev_setbsz (guestfs_h *g, > int blocksize) > { > struct guestfs_blockdev_setbsz_args args; > - struct blockdev_setbsz_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_setbsz") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.blocksize = blocksize; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_SETBSZ, > @@ -5580,90 +4999,77 @@ int guestfs_blockdev_setbsz (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_setbsz_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_getsz_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_blockdev_getsz_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_setbsz"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_getsz_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_getsz_ctx *ctx = (struct blockdev_getsz_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_setbsz"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getsz"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_setbsz"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_setbsz"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_blockdev_getsz_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_SETBSZ, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int64_t guestfs_blockdev_getsz (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_getsz_args args; > - struct blockdev_getsz_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_blockdev_getsz_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_getsz") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSZ, > (xdrproc_t) xdr_guestfs_blockdev_getsz_args, (char *) &args); > @@ -5672,90 +5078,81 @@ int64_t guestfs_blockdev_getsz (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_getsz_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.sizeinsectors; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_getsize64_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_blockdev_getsize64_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_getsz"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_getsize64_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_getsize64_ctx *ctx = (struct blockdev_getsize64_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsz"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_getsize64"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsz"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsz"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_blockdev_getsize64_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64"); > - return; > + else if (!xdr_guestfs_blockdev_getsz_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_blockdev_getsz"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_GETSZ, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.sizeinsectors; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int64_t guestfs_blockdev_getsize64 (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_getsize64_args args; > - struct blockdev_getsize64_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_blockdev_getsize64_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_getsize64") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_GETSIZE64, > (xdrproc_t) xdr_guestfs_blockdev_getsize64_args, (char *) &args); > @@ -5764,85 +5161,80 @@ int64_t guestfs_blockdev_getsize64 (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_getsize64_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.sizeinbytes; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_flushbufs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_getsize64"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_flushbufs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_flushbufs_ctx *ctx = (struct blockdev_flushbufs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_getsize64"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_flushbufs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_getsize64"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_getsize64"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_blockdev_getsize64_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_blockdev_getsize64"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_GETSIZE64, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.sizeinbytes; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_flushbufs (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_flushbufs_args args; > - struct blockdev_flushbufs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_flushbufs") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, > (xdrproc_t) xdr_guestfs_blockdev_flushbufs_args, (char *) &args); > @@ -5851,85 +5243,76 @@ int guestfs_blockdev_flushbufs (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_flushbufs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct blockdev_rereadpt_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_flushbufs"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void blockdev_rereadpt_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct blockdev_rereadpt_ctx *ctx = (struct blockdev_rereadpt_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_flushbufs"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_blockdev_rereadpt"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_flushbufs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_flushbufs"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_FLUSHBUFS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_blockdev_rereadpt (guestfs_h *g, > const char *device) > { > struct guestfs_blockdev_rereadpt_args args; > - struct blockdev_rereadpt_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_blockdev_rereadpt") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_BLOCKDEV_REREADPT, > (xdrproc_t) xdr_guestfs_blockdev_rereadpt_args, (char *) &args); > @@ -5938,70 +5321,63 @@ int guestfs_blockdev_rereadpt (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, blockdev_rereadpt_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct upload_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_blockdev_rereadpt"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void upload_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct upload_ctx *ctx = (struct upload_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_blockdev_rereadpt"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_upload"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_upload"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_blockdev_rereadpt"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_upload"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_blockdev_rereadpt"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_BLOCKDEV_REREADPT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_upload (guestfs_h *g, > @@ -6009,15 +5385,13 @@ int guestfs_upload (guestfs_h *g, > const char *remotefilename) > { > struct guestfs_upload_args args; > - struct upload_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_upload") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.remotefilename = (char *) remotefilename; > serial = guestfs__send_sync (g, GUESTFS_PROC_UPLOAD, > (xdrproc_t) xdr_guestfs_upload_args, (char *) &args); > @@ -6034,75 +5408,65 @@ int guestfs_upload (guestfs_h *g, > guestfs_end_busy (g); > return -1; > } > - if (r == -2) /* daemon cancelled */ > - goto read_reply; > - } > - > - read_reply: > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, upload_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_upload"); > - guestfs_end_busy (g); > - return -1; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UPLOAD, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct download_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_upload"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void download_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct download_ctx *ctx = (struct download_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_upload"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_download"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_download"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_upload"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_download"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_upload"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_UPLOAD, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_download (guestfs_h *g, > @@ -6110,15 +5474,13 @@ int guestfs_download (guestfs_h *g, > const char *filename) > { > struct guestfs_download_args args; > - struct download_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_download") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.remotefilename = (char *) remotefilename; > serial = guestfs__send_sync (g, GUESTFS_PROC_DOWNLOAD, > (xdrproc_t) xdr_guestfs_download_args, (char *) &args); > @@ -6127,80 +5489,68 @@ int guestfs_download (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, download_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_download"); > - guestfs_end_busy (g); > - return -1; > + guestfs_reply_t reply; > + > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > + > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > + > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_download"); > + guestfs_end_busy (g); > + return -1; > + } > + > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_download"); > + guestfs_end_busy (g); > + return -1; > + } > + > + break; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_download"); > + goto recv_error; > } > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_download"); > + goto recv_error; > + } > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DOWNLOAD, serial) == -1) { > + goto recv_error; > } > > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > if (guestfs__receive_file_sync (g, filename) == -1) { > guestfs_end_busy (g); > return -1; > } > > guestfs_end_busy (g); > - return 0; > -} > - > -struct checksum_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_checksum_ret ret; > -}; > - > -static void checksum_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct checksum_ctx *ctx = (struct checksum_ctx *) data; > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_checksum"); > - return; > - } > - > - ml->main_loop_quit (ml, g); > + return 0; > > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_checksum"); > - return; > - } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_checksum"); > - return; > - } > - goto done; > - } > - if (!xdr_guestfs_checksum_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_checksum"); > - return; > - } > - done: > - ctx->cb_sequence = 1; > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_checksum (guestfs_h *g, > @@ -6208,15 +5558,14 @@ char *guestfs_checksum (guestfs_h *g, > const char *path) > { > struct guestfs_checksum_args args; > - struct checksum_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_checksum_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_checksum") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.csumtype = (char *) csumtype; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_CHECKSUM, > @@ -6226,70 +5575,67 @@ char *guestfs_checksum (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, checksum_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_checksum"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CHECKSUM, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.checksum; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tar_in_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_checksum"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void tar_in_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tar_in_ctx *ctx = (struct tar_in_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_checksum"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tar_in"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tar_in"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_checksum"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tar_in"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_checksum"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_checksum_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_checksum"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CHECKSUM, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.checksum; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_tar_in (guestfs_h *g, > @@ -6297,15 +5643,13 @@ int guestfs_tar_in (guestfs_h *g, > const char *directory) > { > struct guestfs_tar_in_args args; > - struct tar_in_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_tar_in") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_TAR_IN, > (xdrproc_t) xdr_guestfs_tar_in_args, (char *) &args); > @@ -6322,75 +5666,65 @@ int guestfs_tar_in (guestfs_h *g, > guestfs_end_busy (g); > return -1; > } > - if (r == -2) /* daemon cancelled */ > - goto read_reply; > - } > - > - read_reply: > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tar_in_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tar_in"); > - guestfs_end_busy (g); > - return -1; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAR_IN, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tar_out_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tar_in"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void tar_out_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tar_out_ctx *ctx = (struct tar_out_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tar_in"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tar_out"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tar_out"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tar_in"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tar_out"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tar_in"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TAR_IN, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_tar_out (guestfs_h *g, > @@ -6398,15 +5732,13 @@ int guestfs_tar_out (guestfs_h *g, > const char *tarfile) > { > struct guestfs_tar_out_args args; > - struct tar_out_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_tar_out") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_TAR_OUT, > (xdrproc_t) xdr_guestfs_tar_out_args, (char *) &args); > @@ -6415,75 +5747,68 @@ int guestfs_tar_out (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tar_out_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tar_out"); > - guestfs_end_busy (g); > - return -1; > + guestfs_reply_t reply; > + > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > + > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > + > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tar_out"); > + guestfs_end_busy (g); > + return -1; > + } > + > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tar_out"); > + guestfs_end_busy (g); > + return -1; > + } > + > + break; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAR_OUT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tar_out"); > + goto recv_error; > } > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tar_out"); > + goto recv_error; > + } > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TAR_OUT, serial) == -1) { > + goto recv_error; > } > > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > if (guestfs__receive_file_sync (g, tarfile) == -1) { > guestfs_end_busy (g); > return -1; > } > > guestfs_end_busy (g); > - return 0; > -} > - > -struct tgz_in_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > - > -static void tgz_in_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tgz_in_ctx *ctx = (struct tgz_in_ctx *) data; > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tgz_in"); > - return; > - } > - > - ml->main_loop_quit (ml, g); > + return 0; > > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tgz_in"); > - return; > - } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tgz_in"); > - return; > - } > - goto done; > - } > - done: > - ctx->cb_sequence = 1; > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_tgz_in (guestfs_h *g, > @@ -6491,15 +5816,13 @@ int guestfs_tgz_in (guestfs_h *g, > const char *directory) > { > struct guestfs_tgz_in_args args; > - struct tgz_in_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_tgz_in") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_TGZ_IN, > (xdrproc_t) xdr_guestfs_tgz_in_args, (char *) &args); > @@ -6516,75 +5839,65 @@ int guestfs_tgz_in (guestfs_h *g, > guestfs_end_busy (g); > return -1; > } > - if (r == -2) /* daemon cancelled */ > - goto read_reply; > } > > - read_reply: > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tgz_in_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_in"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TGZ_IN, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tgz_out_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tgz_in"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void tgz_out_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tgz_out_ctx *ctx = (struct tgz_out_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_in"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tgz_out"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tgz_out"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tgz_in"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tgz_out"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tgz_in"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TGZ_IN, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_tgz_out (guestfs_h *g, > @@ -6592,15 +5905,13 @@ int guestfs_tgz_out (guestfs_h *g, > const char *tarball) > { > struct guestfs_tgz_out_args args; > - struct tgz_out_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_tgz_out") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_TGZ_OUT, > (xdrproc_t) xdr_guestfs_tgz_out_args, (char *) &args); > @@ -6609,75 +5920,68 @@ int guestfs_tgz_out (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tgz_out_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_out"); > - guestfs_end_busy (g); > - return -1; > + guestfs_reply_t reply; > + > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > + > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > + > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tgz_out"); > + guestfs_end_busy (g); > + return -1; > + } > + > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tgz_out"); > + guestfs_end_busy (g); > + return -1; > + } > + > + break; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TGZ_OUT, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tgz_out"); > + goto recv_error; > } > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tgz_out"); > + goto recv_error; > + } > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TGZ_OUT, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > > + guestfs_free_reply (g, &reply); > + > if (guestfs__receive_file_sync (g, tarball) == -1) { > guestfs_end_busy (g); > return -1; > } > > guestfs_end_busy (g); > - return 0; > -} > - > -struct mount_ro_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > > -static void mount_ro_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mount_ro_ctx *ctx = (struct mount_ro_ctx *) data; > - > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mount_ro"); > - return; > - } > - > - ml->main_loop_quit (ml, g); > + return 0; > > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mount_ro"); > - return; > - } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mount_ro"); > - return; > - } > - goto done; > - } > - done: > - ctx->cb_sequence = 1; > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mount_ro (guestfs_h *g, > @@ -6685,15 +5989,13 @@ int guestfs_mount_ro (guestfs_h *g, > const char *mountpoint) > { > struct guestfs_mount_ro_args args; > - struct mount_ro_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mount_ro") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.mountpoint = (char *) mountpoint; > serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_RO, > @@ -6703,70 +6005,63 @@ int guestfs_mount_ro (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mount_ro_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mount_ro"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_RO, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mount_options_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mount_ro"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mount_options_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mount_options_ctx *ctx = (struct mount_options_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_ro"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mount_options"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mount_options"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mount_ro"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mount_options"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mount_ro"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNT_RO, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mount_options (guestfs_h *g, > @@ -6775,15 +6070,13 @@ int guestfs_mount_options (guestfs_h *g, > const char *mountpoint) > { > struct guestfs_mount_options_args args; > - struct mount_options_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mount_options") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.options = (char *) options; > args.device = (char *) device; > args.mountpoint = (char *) mountpoint; > @@ -6794,70 +6087,63 @@ int guestfs_mount_options (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mount_options_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mount_options"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_OPTIONS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mount_vfs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mount_options"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mount_vfs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mount_vfs_ctx *ctx = (struct mount_vfs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_options"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mount_vfs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mount_vfs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mount_options"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mount_vfs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mount_options"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNT_OPTIONS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mount_vfs (guestfs_h *g, > @@ -6867,15 +6153,13 @@ int guestfs_mount_vfs (guestfs_h *g, > const char *mountpoint) > { > struct guestfs_mount_vfs_args args; > - struct mount_vfs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mount_vfs") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.options = (char *) options; > args.vfstype = (char *) vfstype; > args.device = (char *) device; > @@ -6887,75 +6171,63 @@ int guestfs_mount_vfs (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mount_vfs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mount_vfs"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_VFS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct debug_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_debug_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mount_vfs"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void debug_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct debug_ctx *ctx = (struct debug_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_vfs"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_debug"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_debug"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mount_vfs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_debug"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mount_vfs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_debug_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_debug"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNT_VFS, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_debug (guestfs_h *g, > @@ -6963,15 +6235,14 @@ char *guestfs_debug (guestfs_h *g, > char * const* const extraargs) > { > struct guestfs_debug_args args; > - struct debug_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_debug_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_debug") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.subcmd = (char *) subcmd; > args.extraargs.extraargs_val = (char **) extraargs; > for (args.extraargs.extraargs_len = 0; extraargs[args.extraargs.extraargs_len]; args.extraargs.extraargs_len++) ; > @@ -6982,85 +6253,80 @@ char *guestfs_debug (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, debug_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_debug"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DEBUG, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.result; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvremove_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_debug"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void lvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvremove_ctx *ctx = (struct lvremove_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_debug"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvremove"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvremove"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_debug"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvremove"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_debug"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_debug_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_debug"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DEBUG, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.result; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_lvremove (guestfs_h *g, > const char *device) > { > struct guestfs_lvremove_args args; > - struct lvremove_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_lvremove") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_LVREMOVE, > (xdrproc_t) xdr_guestfs_lvremove_args, (char *) &args); > @@ -7069,85 +6335,76 @@ int guestfs_lvremove (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvremove_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvremove"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVREMOVE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vgremove_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvremove"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void vgremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vgremove_ctx *ctx = (struct vgremove_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvremove"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vgremove"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vgremove"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvremove"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vgremove"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvremove"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVREMOVE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_vgremove (guestfs_h *g, > const char *vgname) > { > struct guestfs_vgremove_args args; > - struct vgremove_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_vgremove") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.vgname = (char *) vgname; > serial = guestfs__send_sync (g, GUESTFS_PROC_VGREMOVE, > (xdrproc_t) xdr_guestfs_vgremove_args, (char *) &args); > @@ -7156,85 +6413,76 @@ int guestfs_vgremove (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vgremove_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vgremove"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGREMOVE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct pvremove_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vgremove"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void pvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct pvremove_ctx *ctx = (struct pvremove_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vgremove"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_pvremove"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_pvremove"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vgremove"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_pvremove"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vgremove"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VGREMOVE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_pvremove (guestfs_h *g, > const char *device) > { > struct guestfs_pvremove_args args; > - struct pvremove_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_pvremove") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_PVREMOVE, > (xdrproc_t) xdr_guestfs_pvremove_args, (char *) &args); > @@ -7243,70 +6491,63 @@ int guestfs_pvremove (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, pvremove_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_pvremove"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVREMOVE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct set_e2label_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_pvremove"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void set_e2label_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct set_e2label_ctx *ctx = (struct set_e2label_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_pvremove"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_set_e2label"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_set_e2label"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_pvremove"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_set_e2label"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_pvremove"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PVREMOVE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_set_e2label (guestfs_h *g, > @@ -7314,15 +6555,13 @@ int guestfs_set_e2label (guestfs_h *g, > const char *label) > { > struct guestfs_set_e2label_args args; > - struct set_e2label_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_set_e2label") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.label = (char *) label; > serial = guestfs__send_sync (g, GUESTFS_PROC_SET_E2LABEL, > @@ -7332,90 +6571,77 @@ int guestfs_set_e2label (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, set_e2label_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2label"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SET_E2LABEL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct get_e2label_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_get_e2label_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_set_e2label"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void get_e2label_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct get_e2label_ctx *ctx = (struct get_e2label_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2label"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_get_e2label"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_get_e2label"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_set_e2label"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_get_e2label"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_set_e2label"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_get_e2label_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_get_e2label"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SET_E2LABEL, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_get_e2label (guestfs_h *g, > const char *device) > { > struct guestfs_get_e2label_args args; > - struct get_e2label_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_get_e2label_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_get_e2label") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_GET_E2LABEL, > (xdrproc_t) xdr_guestfs_get_e2label_args, (char *) &args); > @@ -7424,70 +6650,67 @@ char *guestfs_get_e2label (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, get_e2label_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2label"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GET_E2LABEL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.label; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct set_e2uuid_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_get_e2label"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void set_e2uuid_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct set_e2uuid_ctx *ctx = (struct set_e2uuid_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2label"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_set_e2uuid"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_set_e2uuid"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_get_e2label"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_set_e2uuid"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_get_e2label"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_get_e2label_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_get_e2label"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_GET_E2LABEL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.label; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_set_e2uuid (guestfs_h *g, > @@ -7495,15 +6718,13 @@ int guestfs_set_e2uuid (guestfs_h *g, > const char *uuid) > { > struct guestfs_set_e2uuid_args args; > - struct set_e2uuid_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_set_e2uuid") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.uuid = (char *) uuid; > serial = guestfs__send_sync (g, GUESTFS_PROC_SET_E2UUID, > @@ -7513,90 +6734,77 @@ int guestfs_set_e2uuid (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, set_e2uuid_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2uuid"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SET_E2UUID, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct get_e2uuid_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_get_e2uuid_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_set_e2uuid"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void get_e2uuid_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct get_e2uuid_ctx *ctx = (struct get_e2uuid_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_set_e2uuid"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_get_e2uuid"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_get_e2uuid"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_set_e2uuid"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_get_e2uuid"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_set_e2uuid"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_get_e2uuid_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_get_e2uuid"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SET_E2UUID, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_get_e2uuid (guestfs_h *g, > const char *device) > { > struct guestfs_get_e2uuid_args args; > - struct get_e2uuid_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_get_e2uuid_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_get_e2uuid") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_GET_E2UUID, > (xdrproc_t) xdr_guestfs_get_e2uuid_args, (char *) &args); > @@ -7605,75 +6813,67 @@ char *guestfs_get_e2uuid (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, get_e2uuid_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2uuid"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GET_E2UUID, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.uuid; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct fsck_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_fsck_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_get_e2uuid"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void fsck_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct fsck_ctx *ctx = (struct fsck_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_get_e2uuid"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_fsck"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_fsck"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_get_e2uuid"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_fsck"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_get_e2uuid"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_fsck_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_fsck"); > - return; > + else if (!xdr_guestfs_get_e2uuid_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_get_e2uuid"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_GET_E2UUID, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.uuid; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_fsck (guestfs_h *g, > @@ -7681,15 +6881,14 @@ int guestfs_fsck (guestfs_h *g, > const char *device) > { > struct guestfs_fsck_args args; > - struct fsck_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_fsck_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_fsck") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.fstype = (char *) fstype; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_FSCK, > @@ -7699,85 +6898,80 @@ int guestfs_fsck (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, fsck_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_fsck"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FSCK, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.status; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct zero_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_fsck"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void zero_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct zero_ctx *ctx = (struct zero_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_fsck"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_zero"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_zero"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_fsck"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_zero"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_fsck"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_fsck_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_fsck"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_FSCK, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.status; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_zero (guestfs_h *g, > const char *device) > { > struct guestfs_zero_args args; > - struct zero_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_zero") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_ZERO, > (xdrproc_t) xdr_guestfs_zero_args, (char *) &args); > @@ -7786,70 +6980,63 @@ int guestfs_zero (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, zero_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_zero"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_ZERO, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct grub_install_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_zero"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void grub_install_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct grub_install_ctx *ctx = (struct grub_install_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_zero"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_grub_install"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_grub_install"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_zero"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_grub_install"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_zero"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_ZERO, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_grub_install (guestfs_h *g, > @@ -7857,15 +7044,13 @@ int guestfs_grub_install (guestfs_h *g, > const char *device) > { > struct guestfs_grub_install_args args; > - struct grub_install_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_grub_install") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.root = (char *) root; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_GRUB_INSTALL, > @@ -7875,70 +7060,63 @@ int guestfs_grub_install (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, grub_install_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_grub_install"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GRUB_INSTALL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct cp_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_grub_install"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void cp_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct cp_ctx *ctx = (struct cp_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_grub_install"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_cp"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_cp"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_grub_install"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_cp"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_grub_install"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_GRUB_INSTALL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_cp (guestfs_h *g, > @@ -7946,15 +7124,13 @@ int guestfs_cp (guestfs_h *g, > const char *dest) > { > struct guestfs_cp_args args; > - struct cp_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_cp") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.src = (char *) src; > args.dest = (char *) dest; > serial = guestfs__send_sync (g, GUESTFS_PROC_CP, > @@ -7964,70 +7140,63 @@ int guestfs_cp (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, cp_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_cp"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CP, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct cp_a_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_cp"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void cp_a_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct cp_a_ctx *ctx = (struct cp_a_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_cp"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_cp_a"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_cp_a"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_cp"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_cp_a"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_cp"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CP, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_cp_a (guestfs_h *g, > @@ -8035,15 +7204,13 @@ int guestfs_cp_a (guestfs_h *g, > const char *dest) > { > struct guestfs_cp_a_args args; > - struct cp_a_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_cp_a") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.src = (char *) src; > args.dest = (char *) dest; > serial = guestfs__send_sync (g, GUESTFS_PROC_CP_A, > @@ -8053,70 +7220,63 @@ int guestfs_cp_a (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, cp_a_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_cp_a"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_CP_A, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mv_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_cp_a"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mv_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mv_ctx *ctx = (struct mv_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_cp_a"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mv"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mv"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_cp_a"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mv"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_cp_a"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_CP_A, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mv (guestfs_h *g, > @@ -8124,15 +7284,13 @@ int guestfs_mv (guestfs_h *g, > const char *dest) > { > struct guestfs_mv_args args; > - struct mv_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mv") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.src = (char *) src; > args.dest = (char *) dest; > serial = guestfs__send_sync (g, GUESTFS_PROC_MV, > @@ -8142,85 +7300,76 @@ int guestfs_mv (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mv_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mv"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MV, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct drop_caches_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mv"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void drop_caches_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct drop_caches_ctx *ctx = (struct drop_caches_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mv"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_drop_caches"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_drop_caches"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mv"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_drop_caches"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mv"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MV, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_drop_caches (guestfs_h *g, > int whattodrop) > { > struct guestfs_drop_caches_args args; > - struct drop_caches_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_drop_caches") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.whattodrop = whattodrop; > serial = guestfs__send_sync (g, GUESTFS_PROC_DROP_CACHES, > (xdrproc_t) xdr_guestfs_drop_caches_args, (char *) &args); > @@ -8229,246 +7378,216 @@ int guestfs_drop_caches (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, drop_caches_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_drop_caches"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DROP_CACHES, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct dmesg_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_dmesg_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_drop_caches"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void dmesg_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct dmesg_ctx *ctx = (struct dmesg_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_drop_caches"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_dmesg"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_dmesg"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_drop_caches"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_dmesg"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_drop_caches"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_dmesg_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_dmesg"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DROP_CACHES, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_dmesg (guestfs_h *g) > { > - struct dmesg_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_dmesg_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_dmesg") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_DMESG, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, dmesg_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_dmesg"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DMESG, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.kmsgs; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct ping_daemon_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_dmesg"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void ping_daemon_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct ping_daemon_ctx *ctx = (struct ping_daemon_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_dmesg"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_ping_daemon"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_ping_daemon"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_dmesg"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_ping_daemon"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_dmesg"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_dmesg_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_dmesg"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DMESG, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.kmsgs; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_ping_daemon (guestfs_h *g) > { > - struct ping_daemon_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_ping_daemon") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_PING_DAEMON, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, ping_daemon_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_ping_daemon"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PING_DAEMON, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct equal_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_equal_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_ping_daemon"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void equal_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct equal_ctx *ctx = (struct equal_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_ping_daemon"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_equal"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_equal"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_ping_daemon"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_equal"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_ping_daemon"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_equal_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_equal"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PING_DAEMON, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_equal (guestfs_h *g, > @@ -8476,15 +7595,14 @@ int guestfs_equal (guestfs_h *g, > const char *file2) > { > struct guestfs_equal_args args; > - struct equal_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_equal_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_equal") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.file1 = (char *) file1; > args.file2 = (char *) file2; > serial = guestfs__send_sync (g, GUESTFS_PROC_EQUAL, > @@ -8494,90 +7612,81 @@ int guestfs_equal (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, equal_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_equal"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_EQUAL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.equality; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct strings_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_strings_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_equal"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void strings_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct strings_ctx *ctx = (struct strings_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_equal"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_strings"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_strings"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_equal"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_strings"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_equal"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_strings_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_strings"); > - return; > + else if (!xdr_guestfs_equal_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_equal"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_EQUAL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.equality; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_strings (guestfs_h *g, > const char *path) > { > struct guestfs_strings_args args; > - struct strings_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_strings_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_strings") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_STRINGS, > (xdrproc_t) xdr_guestfs_strings_args, (char *) &args); > @@ -8586,80 +7695,72 @@ char **guestfs_strings (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, strings_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_strings"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STRINGS, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.stringsout.stringsout_val = > - safe_realloc (g, ctx.ret.stringsout.stringsout_val, > - sizeof (char *) * (ctx.ret.stringsout.stringsout_len + 1)); > - ctx.ret.stringsout.stringsout_val[ctx.ret.stringsout.stringsout_len] = NULL; > - return ctx.ret.stringsout.stringsout_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct strings_e_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_strings_e_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_strings"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void strings_e_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct strings_e_ctx *ctx = (struct strings_e_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_strings"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_strings_e"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_strings_e"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_strings"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_strings_e"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_strings"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_strings_e_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_strings_e"); > - return; > + else if (!xdr_guestfs_strings_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_strings"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_STRINGS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.stringsout.stringsout_val = > + safe_realloc (g, ret.stringsout.stringsout_val, > + sizeof (char *) * (ret.stringsout.stringsout_len + 1)); > + ret.stringsout.stringsout_val[ret.stringsout.stringsout_len] = NULL; > + return ret.stringsout.stringsout_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_strings_e (guestfs_h *g, > @@ -8667,15 +7768,14 @@ char **guestfs_strings_e (guestfs_h *g, > const char *path) > { > struct guestfs_strings_e_args args; > - struct strings_e_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_strings_e_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_strings_e") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.encoding = (char *) encoding; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_STRINGS_E, > @@ -8685,95 +7785,86 @@ char **guestfs_strings_e (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, strings_e_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_strings_e"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_STRINGS_E, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.stringsout.stringsout_val = > - safe_realloc (g, ctx.ret.stringsout.stringsout_val, > - sizeof (char *) * (ctx.ret.stringsout.stringsout_len + 1)); > - ctx.ret.stringsout.stringsout_val[ctx.ret.stringsout.stringsout_len] = NULL; > - return ctx.ret.stringsout.stringsout_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct hexdump_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_hexdump_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_strings_e"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void hexdump_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct hexdump_ctx *ctx = (struct hexdump_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_strings_e"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_hexdump"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_hexdump"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_strings_e"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_hexdump"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_strings_e"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_hexdump_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_hexdump"); > - return; > + else if (!xdr_guestfs_strings_e_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_strings_e"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_STRINGS_E, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.stringsout.stringsout_val = > + safe_realloc (g, ret.stringsout.stringsout_val, > + sizeof (char *) * (ret.stringsout.stringsout_len + 1)); > + ret.stringsout.stringsout_val[ret.stringsout.stringsout_len] = NULL; > + return ret.stringsout.stringsout_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_hexdump (guestfs_h *g, > const char *path) > { > struct guestfs_hexdump_args args; > - struct hexdump_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_hexdump_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_hexdump") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_HEXDUMP, > (xdrproc_t) xdr_guestfs_hexdump_args, (char *) &args); > @@ -8782,85 +7873,80 @@ char *guestfs_hexdump (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, hexdump_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_hexdump"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEXDUMP, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.dump; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct zerofree_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_hexdump"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void zerofree_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct zerofree_ctx *ctx = (struct zerofree_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_hexdump"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_zerofree"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_zerofree"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_hexdump"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_zerofree"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_hexdump"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_hexdump_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_hexdump"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_HEXDUMP, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.dump; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_zerofree (guestfs_h *g, > const char *device) > { > struct guestfs_zerofree_args args; > - struct zerofree_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_zerofree") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_ZEROFREE, > (xdrproc_t) xdr_guestfs_zerofree_args, (char *) &args); > @@ -8869,85 +7955,76 @@ int guestfs_zerofree (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, zerofree_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_zerofree"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_ZEROFREE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct pvresize_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_zerofree"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void pvresize_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct pvresize_ctx *ctx = (struct pvresize_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_zerofree"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_pvresize"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_pvresize"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_zerofree"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_pvresize"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_zerofree"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_ZEROFREE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_pvresize (guestfs_h *g, > const char *device) > { > struct guestfs_pvresize_args args; > - struct pvresize_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_pvresize") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_PVRESIZE, > (xdrproc_t) xdr_guestfs_pvresize_args, (char *) &args); > @@ -8956,70 +8033,63 @@ int guestfs_pvresize (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, pvresize_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_pvresize"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVRESIZE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sfdisk_N_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_pvresize"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sfdisk_N_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sfdisk_N_ctx *ctx = (struct sfdisk_N_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_pvresize"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_N"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sfdisk_N"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_pvresize"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sfdisk_N"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_pvresize"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_PVRESIZE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_sfdisk_N (guestfs_h *g, > @@ -9031,15 +8101,13 @@ int guestfs_sfdisk_N (guestfs_h *g, > const char *line) > { > struct guestfs_sfdisk_N_args args; > - struct sfdisk_N_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_sfdisk_N") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.partnum = partnum; > args.cyls = cyls; > @@ -9053,90 +8121,77 @@ int guestfs_sfdisk_N (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sfdisk_N_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_N"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_N, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sfdisk_l_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_sfdisk_l_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sfdisk_N"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sfdisk_l_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sfdisk_l_ctx *ctx = (struct sfdisk_l_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_N"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_l"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sfdisk_l"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sfdisk_N"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sfdisk_l"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sfdisk_N"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_sfdisk_l_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_sfdisk_l"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SFDISK_N, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_sfdisk_l (guestfs_h *g, > const char *device) > { > struct guestfs_sfdisk_l_args args; > - struct sfdisk_l_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_sfdisk_l_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_sfdisk_l") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_L, > (xdrproc_t) xdr_guestfs_sfdisk_l_args, (char *) &args); > @@ -9145,90 +8200,81 @@ char *guestfs_sfdisk_l (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sfdisk_l_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_l"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_L, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.partitions; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sfdisk_kernel_geometry_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_sfdisk_kernel_geometry_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sfdisk_l"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void sfdisk_kernel_geometry_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sfdisk_kernel_geometry_ctx *ctx = (struct sfdisk_kernel_geometry_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_l"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_kernel_geometry"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sfdisk_kernel_geometry"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sfdisk_l"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sfdisk_kernel_geometry"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sfdisk_l"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_sfdisk_kernel_geometry_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_sfdisk_kernel_geometry"); > - return; > + else if (!xdr_guestfs_sfdisk_l_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_sfdisk_l"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SFDISK_L, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.partitions; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_sfdisk_kernel_geometry (guestfs_h *g, > const char *device) > { > struct guestfs_sfdisk_kernel_geometry_args args; > - struct sfdisk_kernel_geometry_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_sfdisk_kernel_geometry_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_sfdisk_kernel_geometry") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY, > (xdrproc_t) xdr_guestfs_sfdisk_kernel_geometry_args, (char *) &args); > @@ -9237,90 +8283,81 @@ char *guestfs_sfdisk_kernel_geometry (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sfdisk_kernel_geometry_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_kernel_geometry"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.partitions; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sfdisk_disk_geometry_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_sfdisk_disk_geometry_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sfdisk_kernel_geometry"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void sfdisk_disk_geometry_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sfdisk_disk_geometry_ctx *ctx = (struct sfdisk_disk_geometry_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_kernel_geometry"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sfdisk_disk_geometry"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sfdisk_disk_geometry"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sfdisk_kernel_geometry"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sfdisk_disk_geometry"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sfdisk_kernel_geometry"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_sfdisk_disk_geometry_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_sfdisk_disk_geometry"); > - return; > + else if (!xdr_guestfs_sfdisk_kernel_geometry_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_sfdisk_kernel_geometry"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SFDISK_KERNEL_GEOMETRY, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.partitions; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_sfdisk_disk_geometry (guestfs_h *g, > const char *device) > { > struct guestfs_sfdisk_disk_geometry_args args; > - struct sfdisk_disk_geometry_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_sfdisk_disk_geometry_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_sfdisk_disk_geometry") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_SFDISK_DISK_GEOMETRY, > (xdrproc_t) xdr_guestfs_sfdisk_disk_geometry_args, (char *) &args); > @@ -9329,85 +8366,80 @@ char *guestfs_sfdisk_disk_geometry (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sfdisk_disk_geometry_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_disk_geometry"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SFDISK_DISK_GEOMETRY, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.partitions; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vg_activate_all_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sfdisk_disk_geometry"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void vg_activate_all_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vg_activate_all_ctx *ctx = (struct vg_activate_all_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sfdisk_disk_geometry"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vg_activate_all"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vg_activate_all"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sfdisk_disk_geometry"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vg_activate_all"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sfdisk_disk_geometry"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_sfdisk_disk_geometry_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_sfdisk_disk_geometry"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SFDISK_DISK_GEOMETRY, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.partitions; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_vg_activate_all (guestfs_h *g, > int activate) > { > struct guestfs_vg_activate_all_args args; > - struct vg_activate_all_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_vg_activate_all") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.activate = activate; > serial = guestfs__send_sync (g, GUESTFS_PROC_VG_ACTIVATE_ALL, > (xdrproc_t) xdr_guestfs_vg_activate_all_args, (char *) &args); > @@ -9416,70 +8448,63 @@ int guestfs_vg_activate_all (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vg_activate_all_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate_all"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VG_ACTIVATE_ALL, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct vg_activate_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vg_activate_all"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void vg_activate_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct vg_activate_ctx *ctx = (struct vg_activate_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate_all"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_vg_activate"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_vg_activate"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vg_activate_all"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_vg_activate"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vg_activate_all"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VG_ACTIVATE_ALL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_vg_activate (guestfs_h *g, > @@ -9487,15 +8512,13 @@ int guestfs_vg_activate (guestfs_h *g, > char * const* const volgroups) > { > struct guestfs_vg_activate_args args; > - struct vg_activate_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_vg_activate") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.activate = activate; > args.volgroups.volgroups_val = (char **) volgroups; > for (args.volgroups.volgroups_len = 0; volgroups[args.volgroups.volgroups_len]; args.volgroups.volgroups_len++) ; > @@ -9506,70 +8529,63 @@ int guestfs_vg_activate (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, vg_activate_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VG_ACTIVATE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct lvresize_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_vg_activate"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void lvresize_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct lvresize_ctx *ctx = (struct lvresize_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_vg_activate"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_lvresize"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_lvresize"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_vg_activate"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_lvresize"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_vg_activate"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_VG_ACTIVATE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_lvresize (guestfs_h *g, > @@ -9577,15 +8593,13 @@ int guestfs_lvresize (guestfs_h *g, > int mbytes) > { > struct guestfs_lvresize_args args; > - struct lvresize_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_lvresize") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > args.mbytes = mbytes; > serial = guestfs__send_sync (g, GUESTFS_PROC_LVRESIZE, > @@ -9595,85 +8609,76 @@ int guestfs_lvresize (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, lvresize_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_lvresize"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVRESIZE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct resize2fs_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_lvresize"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void resize2fs_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct resize2fs_ctx *ctx = (struct resize2fs_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_lvresize"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_resize2fs"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_resize2fs"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_lvresize"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_resize2fs"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_lvresize"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_LVRESIZE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_resize2fs (guestfs_h *g, > const char *device) > { > struct guestfs_resize2fs_args args; > - struct resize2fs_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_resize2fs") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_RESIZE2FS, > (xdrproc_t) xdr_guestfs_resize2fs_args, (char *) &args); > @@ -9682,90 +8687,77 @@ int guestfs_resize2fs (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, resize2fs_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_resize2fs"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_RESIZE2FS, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct find_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_find_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_resize2fs"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void find_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct find_ctx *ctx = (struct find_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_resize2fs"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_find"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_find"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_resize2fs"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_find"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_resize2fs"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_find_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_find"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_RESIZE2FS, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_find (guestfs_h *g, > const char *directory) > { > struct guestfs_find_args args; > - struct find_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_find_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_find") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.directory = (char *) directory; > serial = guestfs__send_sync (g, GUESTFS_PROC_FIND, > (xdrproc_t) xdr_guestfs_find_args, (char *) &args); > @@ -9774,90 +8766,85 @@ char **guestfs_find (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, find_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_find"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_FIND, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.names.names_val = > - safe_realloc (g, ctx.ret.names.names_val, > - sizeof (char *) * (ctx.ret.names.names_len + 1)); > - ctx.ret.names.names_val[ctx.ret.names.names_len] = NULL; > - return ctx.ret.names.names_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct e2fsck_f_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_find"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void e2fsck_f_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct e2fsck_f_ctx *ctx = (struct e2fsck_f_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_find"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_e2fsck_f"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_e2fsck_f"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_find"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_e2fsck_f"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_find"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_find_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_find"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_FIND, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.names.names_val = > + safe_realloc (g, ret.names.names_val, > + sizeof (char *) * (ret.names.names_len + 1)); > + ret.names.names_val[ret.names.names_len] = NULL; > + return ret.names.names_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_e2fsck_f (guestfs_h *g, > const char *device) > { > struct guestfs_e2fsck_f_args args; > - struct e2fsck_f_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_e2fsck_f") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_E2FSCK_F, > (xdrproc_t) xdr_guestfs_e2fsck_f_args, (char *) &args); > @@ -9866,85 +8853,76 @@ int guestfs_e2fsck_f (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, e2fsck_f_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_e2fsck_f"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_E2FSCK_F, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sleep_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_e2fsck_f"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sleep_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sleep_ctx *ctx = (struct sleep_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_e2fsck_f"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sleep"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sleep"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_e2fsck_f"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sleep"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_e2fsck_f"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_E2FSCK_F, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_sleep (guestfs_h *g, > int secs) > { > struct guestfs_sleep_args args; > - struct sleep_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_sleep") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.secs = secs; > serial = guestfs__send_sync (g, GUESTFS_PROC_SLEEP, > (xdrproc_t) xdr_guestfs_sleep_args, (char *) &args); > @@ -9953,75 +8931,63 @@ int guestfs_sleep (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sleep_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sleep"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SLEEP, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct ntfs_3g_probe_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_ntfs_3g_probe_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sleep"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void ntfs_3g_probe_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct ntfs_3g_probe_ctx *ctx = (struct ntfs_3g_probe_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sleep"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_ntfs_3g_probe"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_ntfs_3g_probe"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sleep"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_ntfs_3g_probe"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sleep"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_ntfs_3g_probe_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_ntfs_3g_probe"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SLEEP, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_ntfs_3g_probe (guestfs_h *g, > @@ -10029,15 +8995,14 @@ int guestfs_ntfs_3g_probe (guestfs_h *g, > const char *device) > { > struct guestfs_ntfs_3g_probe_args args; > - struct ntfs_3g_probe_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_ntfs_3g_probe_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_ntfs_3g_probe") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.rw = rw; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_NTFS_3G_PROBE, > @@ -10047,90 +9012,81 @@ int guestfs_ntfs_3g_probe (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, ntfs_3g_probe_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_ntfs_3g_probe"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_NTFS_3G_PROBE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.status; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sh_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_sh_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_ntfs_3g_probe"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void sh_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sh_ctx *ctx = (struct sh_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_ntfs_3g_probe"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sh"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sh"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_ntfs_3g_probe"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sh"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_ntfs_3g_probe"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_sh_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_sh"); > - return; > + else if (!xdr_guestfs_ntfs_3g_probe_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_ntfs_3g_probe"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_NTFS_3G_PROBE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.status; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_sh (guestfs_h *g, > const char *command) > { > struct guestfs_sh_args args; > - struct sh_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_sh_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_sh") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.command = (char *) command; > serial = guestfs__send_sync (g, GUESTFS_PROC_SH, > (xdrproc_t) xdr_guestfs_sh_args, (char *) &args); > @@ -10139,90 +9095,81 @@ char *guestfs_sh (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sh_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sh"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SH, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.output; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct sh_lines_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_sh_lines_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sh"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void sh_lines_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct sh_lines_ctx *ctx = (struct sh_lines_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sh"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_sh_lines"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_sh_lines"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sh"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_sh_lines"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sh"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_sh_lines_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_sh_lines"); > - return; > + else if (!xdr_guestfs_sh_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_sh"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SH, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.output; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_sh_lines (guestfs_h *g, > const char *command) > { > struct guestfs_sh_lines_args args; > - struct sh_lines_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_sh_lines_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_sh_lines") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.command = (char *) command; > serial = guestfs__send_sync (g, GUESTFS_PROC_SH_LINES, > (xdrproc_t) xdr_guestfs_sh_lines_args, (char *) &args); > @@ -10231,95 +9178,86 @@ char **guestfs_sh_lines (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, sh_lines_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_sh_lines"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SH_LINES, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct glob_expand_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_glob_expand_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_sh_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void glob_expand_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct glob_expand_ctx *ctx = (struct glob_expand_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_sh_lines"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_glob_expand"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_glob_expand"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_sh_lines"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_glob_expand"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_sh_lines"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_glob_expand_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_glob_expand"); > - return; > + else if (!xdr_guestfs_sh_lines_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_sh_lines"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SH_LINES, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_glob_expand (guestfs_h *g, > const char *pattern) > { > struct guestfs_glob_expand_args args; > - struct glob_expand_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_glob_expand_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_glob_expand") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.pattern = (char *) pattern; > serial = guestfs__send_sync (g, GUESTFS_PROC_GLOB_EXPAND, > (xdrproc_t) xdr_guestfs_glob_expand_args, (char *) &args); > @@ -10328,90 +9266,85 @@ char **guestfs_glob_expand (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, glob_expand_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_glob_expand"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_GLOB_EXPAND, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.paths.paths_val = > - safe_realloc (g, ctx.ret.paths.paths_val, > - sizeof (char *) * (ctx.ret.paths.paths_len + 1)); > - ctx.ret.paths.paths_val[ctx.ret.paths.paths_len] = NULL; > - return ctx.ret.paths.paths_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct scrub_device_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_glob_expand"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void scrub_device_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct scrub_device_ctx *ctx = (struct scrub_device_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_glob_expand"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_device"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_scrub_device"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_glob_expand"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_scrub_device"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_glob_expand"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_glob_expand_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_glob_expand"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_GLOB_EXPAND, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.paths.paths_val = > + safe_realloc (g, ret.paths.paths_val, > + sizeof (char *) * (ret.paths.paths_len + 1)); > + ret.paths.paths_val[ret.paths.paths_len] = NULL; > + return ret.paths.paths_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_scrub_device (guestfs_h *g, > const char *device) > { > struct guestfs_scrub_device_args args; > - struct scrub_device_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_scrub_device") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_DEVICE, > (xdrproc_t) xdr_guestfs_scrub_device_args, (char *) &args); > @@ -10420,85 +9353,76 @@ int guestfs_scrub_device (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, scrub_device_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_device"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_DEVICE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct scrub_file_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_scrub_device"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void scrub_file_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct scrub_file_ctx *ctx = (struct scrub_file_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_device"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_file"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_scrub_file"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_scrub_device"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_scrub_file"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_scrub_device"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SCRUB_DEVICE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_scrub_file (guestfs_h *g, > const char *file) > { > struct guestfs_scrub_file_args args; > - struct scrub_file_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_scrub_file") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.file = (char *) file; > serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_FILE, > (xdrproc_t) xdr_guestfs_scrub_file_args, (char *) &args); > @@ -10507,85 +9431,76 @@ int guestfs_scrub_file (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, scrub_file_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_file"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_FILE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct scrub_freespace_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_scrub_file"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void scrub_freespace_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct scrub_freespace_ctx *ctx = (struct scrub_freespace_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_file"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_scrub_freespace"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_scrub_freespace"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_scrub_file"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_scrub_freespace"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_scrub_file"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SCRUB_FILE, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_scrub_freespace (guestfs_h *g, > const char *dir) > { > struct guestfs_scrub_freespace_args args; > - struct scrub_freespace_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_scrub_freespace") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.dir = (char *) dir; > serial = guestfs__send_sync (g, GUESTFS_PROC_SCRUB_FREESPACE, > (xdrproc_t) xdr_guestfs_scrub_freespace_args, (char *) &args); > @@ -10594,90 +9509,77 @@ int guestfs_scrub_freespace (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, scrub_freespace_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_freespace"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_SCRUB_FREESPACE, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkdtemp_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_mkdtemp_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_scrub_freespace"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkdtemp_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkdtemp_ctx *ctx = (struct mkdtemp_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_scrub_freespace"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkdtemp"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkdtemp"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_scrub_freespace"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkdtemp"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_scrub_freespace"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_mkdtemp_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_mkdtemp"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_SCRUB_FREESPACE, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char *guestfs_mkdtemp (guestfs_h *g, > const char *template) > { > struct guestfs_mkdtemp_args args; > - struct mkdtemp_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_mkdtemp_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_mkdtemp") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.template = (char *) template; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKDTEMP, > (xdrproc_t) xdr_guestfs_mkdtemp_args, (char *) &args); > @@ -10686,90 +9588,81 @@ char *guestfs_mkdtemp (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkdtemp_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkdtemp"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKDTEMP, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.dir; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct wc_l_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_wc_l_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkdtemp"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void wc_l_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct wc_l_ctx *ctx = (struct wc_l_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkdtemp"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_wc_l"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_wc_l"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkdtemp"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_wc_l"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkdtemp"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_wc_l_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_wc_l"); > - return; > + else if (!xdr_guestfs_mkdtemp_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_mkdtemp"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKDTEMP, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.dir; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_wc_l (guestfs_h *g, > const char *path) > { > struct guestfs_wc_l_args args; > - struct wc_l_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_wc_l_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_wc_l") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_WC_L, > (xdrproc_t) xdr_guestfs_wc_l_args, (char *) &args); > @@ -10778,90 +9671,81 @@ int guestfs_wc_l (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, wc_l_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_wc_l"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_L, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.lines; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct wc_w_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_wc_w_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_wc_l"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void wc_w_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct wc_w_ctx *ctx = (struct wc_w_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_wc_l"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_wc_w"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_wc_w"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_wc_l"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_wc_w"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_wc_l"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_wc_w_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_wc_w"); > - return; > + else if (!xdr_guestfs_wc_l_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_wc_l"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_WC_L, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.lines; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_wc_w (guestfs_h *g, > const char *path) > { > struct guestfs_wc_w_args args; > - struct wc_w_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_wc_w_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_wc_w") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_WC_W, > (xdrproc_t) xdr_guestfs_wc_w_args, (char *) &args); > @@ -10870,90 +9754,81 @@ int guestfs_wc_w (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, wc_w_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_wc_w"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_W, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.words; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct wc_c_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_wc_c_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_wc_w"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void wc_c_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct wc_c_ctx *ctx = (struct wc_c_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_wc_w"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_wc_c"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_wc_c"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_wc_w"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_wc_c"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_wc_w"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_wc_c_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_wc_c"); > - return; > + else if (!xdr_guestfs_wc_w_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_wc_w"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_WC_W, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.words; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_wc_c (guestfs_h *g, > const char *path) > { > struct guestfs_wc_c_args args; > - struct wc_c_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_wc_c_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_wc_c") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_WC_C, > (xdrproc_t) xdr_guestfs_wc_c_args, (char *) &args); > @@ -10962,90 +9837,81 @@ int guestfs_wc_c (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, wc_c_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_wc_c"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_WC_C, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.chars; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct head_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_head_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_wc_c"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void head_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct head_ctx *ctx = (struct head_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_wc_c"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_head"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_head"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_wc_c"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_head"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_wc_c"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_head_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_head"); > - return; > + else if (!xdr_guestfs_wc_c_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_wc_c"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_WC_C, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.chars; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_head (guestfs_h *g, > const char *path) > { > struct guestfs_head_args args; > - struct head_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_head_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_head") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD, > (xdrproc_t) xdr_guestfs_head_args, (char *) &args); > @@ -11054,80 +9920,72 @@ char **guestfs_head (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, head_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_head"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct head_n_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_head_n_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_head"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void head_n_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct head_n_ctx *ctx = (struct head_n_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_head"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_head_n"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_head_n"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_head"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_head_n"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_head"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_head_n_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_head_n"); > - return; > + else if (!xdr_guestfs_head_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_head"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_HEAD, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_head_n (guestfs_h *g, > @@ -11135,15 +9993,14 @@ char **guestfs_head_n (guestfs_h *g, > const char *path) > { > struct guestfs_head_n_args args; > - struct head_n_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_head_n_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_head_n") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.nrlines = nrlines; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD_N, > @@ -11153,95 +10010,86 @@ char **guestfs_head_n (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, head_n_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_head_n"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD_N, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tail_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_tail_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_head_n"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void tail_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tail_ctx *ctx = (struct tail_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_head_n"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tail"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tail"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_head_n"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tail"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_head_n"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_tail_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_tail"); > - return; > + else if (!xdr_guestfs_head_n_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_head_n"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_HEAD_N, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_tail (guestfs_h *g, > const char *path) > { > struct guestfs_tail_args args; > - struct tail_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_tail_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_tail") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL, > (xdrproc_t) xdr_guestfs_tail_args, (char *) &args); > @@ -11250,80 +10098,72 @@ char **guestfs_tail (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tail_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tail"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct tail_n_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_tail_n_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tail"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void tail_n_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct tail_n_ctx *ctx = (struct tail_n_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tail"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_tail_n"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_tail_n"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tail"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_tail_n"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tail"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_tail_n_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_tail_n"); > - return; > + else if (!xdr_guestfs_tail_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_tail"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TAIL, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char **guestfs_tail_n (guestfs_h *g, > @@ -11331,15 +10171,14 @@ char **guestfs_tail_n (guestfs_h *g, > const char *path) > { > struct guestfs_tail_n_args args; > - struct tail_n_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_tail_n_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_tail_n") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.nrlines = nrlines; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL_N, > @@ -11349,271 +10188,244 @@ char **guestfs_tail_n (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, tail_n_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_tail_n"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL_N, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.lines.lines_val = > - safe_realloc (g, ctx.ret.lines.lines_val, > - sizeof (char *) * (ctx.ret.lines.lines_len + 1)); > - ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL; > - return ctx.ret.lines.lines_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct df_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_df_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_tail_n"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void df_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct df_ctx *ctx = (struct df_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_tail_n"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_df"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_df"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_tail_n"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_df"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_tail_n"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_df_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_df"); > - return; > + else if (!xdr_guestfs_tail_n_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_tail_n"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_TAIL_N, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.lines.lines_val = > + safe_realloc (g, ret.lines.lines_val, > + sizeof (char *) * (ret.lines.lines_len + 1)); > + ret.lines.lines_val[ret.lines.lines_len] = NULL; > + return ret.lines.lines_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_df (guestfs_h *g) > { > - struct df_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_df_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_df") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_DF, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, df_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_df"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DF, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - return ctx.ret.output; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct df_h_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_df_h_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_df"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void df_h_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct df_h_ctx *ctx = (struct df_h_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_df"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_df_h"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_df_h"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_df"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_df_h"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_df"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_df_h_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_df_h"); > - return; > + else if (!xdr_guestfs_df_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_df"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DF, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.output; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > char *guestfs_df_h (guestfs_h *g) > { > - struct df_h_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_df_h_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_df_h") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > serial = guestfs__send_sync (g, GUESTFS_PROC_DF_H, NULL, NULL); > if (serial == -1) { > guestfs_end_busy (g); > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, df_h_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_df_h"); > - guestfs_end_busy (g); > - return NULL; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DF_H, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.output; /* caller will free */ > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct du_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_du_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_df_h"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void du_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct du_ctx *ctx = (struct du_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_df_h"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_du"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_du"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_df_h"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_du"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_df_h"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_du_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_du"); > - return; > + else if (!xdr_guestfs_df_h_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_df_h"); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DF_H, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.output; /* caller will free */ > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int64_t guestfs_du (guestfs_h *g, > const char *path) > { > struct guestfs_du_args args; > - struct du_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_du_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_du") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_DU, > (xdrproc_t) xdr_guestfs_du_args, (char *) &args); > @@ -11622,90 +10434,81 @@ int64_t guestfs_du (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, du_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_du"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_DU, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return ctx.ret.sizekb; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct initrd_list_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_initrd_list_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_du"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void initrd_list_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct initrd_list_ctx *ctx = (struct initrd_list_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_du"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_initrd_list"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_initrd_list"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_du"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_initrd_list"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_du"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_initrd_list_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_initrd_list"); > - return; > + else if (!xdr_guestfs_du_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_du"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_DU, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.sizekb; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > char **guestfs_initrd_list (guestfs_h *g, > const char *path) > { > struct guestfs_initrd_list_args args; > - struct initrd_list_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_initrd_list_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_initrd_list") == -1) return NULL; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_INITRD_LIST, > (xdrproc_t) xdr_guestfs_initrd_list_args, (char *) &args); > @@ -11714,75 +10517,72 @@ char **guestfs_initrd_list (guestfs_h *g, > return NULL; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, initrd_list_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_initrd_list"); > - guestfs_end_busy (g); > - return NULL; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_INITRD_LIST, serial) == -1) { > - guestfs_end_busy (g); > - return NULL; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return NULL; > - } > - > - guestfs_end_busy (g); > - /* caller will free this, but we need to add a NULL entry */ > - ctx.ret.filenames.filenames_val = > - safe_realloc (g, ctx.ret.filenames.filenames_val, > - sizeof (char *) * (ctx.ret.filenames.filenames_len + 1)); > - ctx.ret.filenames.filenames_val[ctx.ret.filenames.filenames_len] = NULL; > - return ctx.ret.filenames.filenames_val; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mount_loop_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_initrd_list"); > + guestfs_end_busy (g); > + return NULL; > + } > > -static void mount_loop_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mount_loop_ctx *ctx = (struct mount_loop_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_initrd_list"); > + guestfs_end_busy (g); > + return NULL; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mount_loop"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mount_loop"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_initrd_list"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mount_loop"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_initrd_list"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + else if (!xdr_guestfs_initrd_list_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_initrd_list"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_INITRD_LIST, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + /* caller will free this, but we need to add a NULL entry */ > + ret.filenames.filenames_val = > + safe_realloc (g, ret.filenames.filenames_val, > + sizeof (char *) * (ret.filenames.filenames_len + 1)); > + ret.filenames.filenames_val[ret.filenames.filenames_len] = NULL; > + return ret.filenames.filenames_val; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return NULL; > } > > int guestfs_mount_loop (guestfs_h *g, > @@ -11790,15 +10590,13 @@ int guestfs_mount_loop (guestfs_h *g, > const char *mountpoint) > { > struct guestfs_mount_loop_args args; > - struct mount_loop_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mount_loop") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.file = (char *) file; > args.mountpoint = (char *) mountpoint; > serial = guestfs__send_sync (g, GUESTFS_PROC_MOUNT_LOOP, > @@ -11808,85 +10606,76 @@ int guestfs_mount_loop (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mount_loop_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mount_loop"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MOUNT_LOOP, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkswap_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mount_loop"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkswap_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkswap_ctx *ctx = (struct mkswap_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mount_loop"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkswap"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkswap"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mount_loop"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkswap"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mount_loop"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MOUNT_LOOP, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkswap (guestfs_h *g, > const char *device) > { > struct guestfs_mkswap_args args; > - struct mkswap_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkswap") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKSWAP, > (xdrproc_t) xdr_guestfs_mkswap_args, (char *) &args); > @@ -11895,70 +10684,63 @@ int guestfs_mkswap (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkswap_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKSWAP, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkswap_L_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkswap"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkswap_L_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkswap_L_ctx *ctx = (struct mkswap_L_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkswap_L"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkswap_L"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkswap"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkswap_L"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkswap"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKSWAP, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkswap_L (guestfs_h *g, > @@ -11966,15 +10748,13 @@ int guestfs_mkswap_L (guestfs_h *g, > const char *device) > { > struct guestfs_mkswap_L_args args; > - struct mkswap_L_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkswap_L") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.label = (char *) label; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKSWAP_L, > @@ -11984,70 +10764,63 @@ int guestfs_mkswap_L (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkswap_L_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap_L"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKSWAP_L, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkswap_U_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkswap_L"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkswap_U_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkswap_U_ctx *ctx = (struct mkswap_U_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap_L"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkswap_U"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkswap_U"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkswap_L"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkswap_U"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkswap_L"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKSWAP_L, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkswap_U (guestfs_h *g, > @@ -12055,15 +10828,13 @@ int guestfs_mkswap_U (guestfs_h *g, > const char *device) > { > struct guestfs_mkswap_U_args args; > - struct mkswap_U_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkswap_U") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.uuid = (char *) uuid; > args.device = (char *) device; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKSWAP_U, > @@ -12073,70 +10844,63 @@ int guestfs_mkswap_U (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkswap_U_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap_U"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKSWAP_U, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mknod_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkswap_U"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mknod_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mknod_ctx *ctx = (struct mknod_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkswap_U"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mknod"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mknod"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkswap_U"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mknod"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkswap_U"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKSWAP_U, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mknod (guestfs_h *g, > @@ -12146,15 +10910,13 @@ int guestfs_mknod (guestfs_h *g, > const char *path) > { > struct guestfs_mknod_args args; > - struct mknod_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mknod") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mode = mode; > args.devmajor = devmajor; > args.devminor = devminor; > @@ -12166,70 +10928,63 @@ int guestfs_mknod (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mknod_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mknod"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKNOD, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mkfifo_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mknod"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mkfifo_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mkfifo_ctx *ctx = (struct mkfifo_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mknod"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mkfifo"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mkfifo"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mknod"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mkfifo"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mknod"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKNOD, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mkfifo (guestfs_h *g, > @@ -12237,15 +10992,13 @@ int guestfs_mkfifo (guestfs_h *g, > const char *path) > { > struct guestfs_mkfifo_args args; > - struct mkfifo_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mkfifo") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mode = mode; > args.path = (char *) path; > serial = guestfs__send_sync (g, GUESTFS_PROC_MKFIFO, > @@ -12255,70 +11008,63 @@ int guestfs_mkfifo (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mkfifo_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mkfifo"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKFIFO, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > - > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mknod_b_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mkfifo"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mknod_b_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mknod_b_ctx *ctx = (struct mknod_b_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mkfifo"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mknod_b"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mknod_b"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mkfifo"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mknod_b"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mkfifo"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKFIFO, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mknod_b (guestfs_h *g, > @@ -12328,15 +11074,13 @@ int guestfs_mknod_b (guestfs_h *g, > const char *path) > { > struct guestfs_mknod_b_args args; > - struct mknod_b_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mknod_b") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mode = mode; > args.devmajor = devmajor; > args.devminor = devminor; > @@ -12348,70 +11092,63 @@ int guestfs_mknod_b (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mknod_b_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mknod_b"); > - guestfs_end_busy (g); > - return -1; > - } > - > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKNOD_B, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct mknod_c_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mknod_b"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void mknod_c_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct mknod_c_ctx *ctx = (struct mknod_c_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mknod_b"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_mknod_c"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_mknod_c"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mknod_b"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_mknod_c"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mknod_b"); > + goto recv_error; > } > - goto done; > } > - done: > - ctx->cb_sequence = 1; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKNOD_B, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_mknod_c (guestfs_h *g, > @@ -12421,15 +11158,13 @@ int guestfs_mknod_c (guestfs_h *g, > const char *path) > { > struct guestfs_mknod_c_args args; > - struct mknod_c_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > int serial; > > if (check_state (g, "guestfs_mknod_c") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mode = mode; > args.devmajor = devmajor; > args.devminor = devminor; > @@ -12441,90 +11176,77 @@ int guestfs_mknod_c (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, mknod_c_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_mknod_c"); > - guestfs_end_busy (g); > - return -1; > - } > + guestfs_reply_t reply; > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_MKNOD_C, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > - } > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > - } > - > - guestfs_end_busy (g); > - return 0; > -} > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > > -struct umask_ctx { > - /* This flag is set by the callbacks, so we know we've done > - * the callbacks as expected, and in the right sequence. > - * 0 = not called, 1 = reply_cb called. > - */ > - int cb_sequence; > - struct guestfs_message_header hdr; > - struct guestfs_message_error err; > - struct guestfs_umask_ret ret; > -}; > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_mknod_c"); > + guestfs_end_busy (g); > + return -1; > + } > > -static void umask_reply_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct umask_ctx *ctx = (struct umask_ctx *) data; > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_mknod_c"); > + guestfs_end_busy (g); > + return -1; > + } > > - /* This should definitely not happen. */ > - if (ctx->cb_sequence != 0) { > - ctx->cb_sequence = 9999; > - error (g, "%s: internal error: reply callback called twice", "guestfs_umask"); > - return; > + break; > } > > - ml->main_loop_quit (ml, g); > - > - if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { > - error (g, "%s: failed to parse reply header", "guestfs_umask"); > - return; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_mknod_c"); > + goto recv_error; > } > - if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { > - if (!xdr_guestfs_message_error (xdr, &ctx->err)) { > - error (g, "%s: failed to parse reply error", "guestfs_umask"); > - return; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_mknod_c"); > + goto recv_error; > } > - goto done; > } > - if (!xdr_guestfs_umask_ret (xdr, &ctx->ret)) { > - error (g, "%s: failed to parse reply", "guestfs_umask"); > - return; > + if (check_reply_header (g, &hdr, GUESTFS_PROC_MKNOD_C, serial) == -1) { > + goto recv_error; > } > - done: > - ctx->cb_sequence = 1; > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > + } > + > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return 0; > + > + recv_error: > + guestfs_free_reply (g, &reply); > + guestfs_end_busy (g); > + return -1; > } > > int guestfs_umask (guestfs_h *g, > int mask) > { > struct guestfs_umask_args args; > - struct umask_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > + struct guestfs_message_header hdr = {}; > + struct guestfs_message_error err = {}; > + struct guestfs_umask_ret ret = {}; > int serial; > > if (check_state (g, "guestfs_umask") == -1) return -1; > guestfs_set_busy (g); > > - memset (&ctx, 0, sizeof ctx); > - > args.mask = mask; > serial = guestfs__send_sync (g, GUESTFS_PROC_UMASK, > (xdrproc_t) xdr_guestfs_umask_args, (char *) &args); > @@ -12533,30 +11255,66 @@ int guestfs_umask (guestfs_h *g, > return -1; > } > > - guestfs__switch_to_receiving (g); > - ctx.cb_sequence = 0; > - guestfs_set_reply_callback (g, umask_reply_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > - if (ctx.cb_sequence != 1) { > - error (g, "%s reply failed, see earlier error messages", "guestfs_umask"); > - guestfs_end_busy (g); > - return -1; > + guestfs_reply_t reply; > + > + for (;;) { > + guestfs_get_reply (g, &reply, 1); > + > + if (GUESTFS_CANCEL_FLAG == reply.len) { > + /* This message was delayed from a previous file transaction. */ > + continue; > + } > + > + if (GUESTFS_LAUNCH_FLAG == reply.len) { > + error (g, "%s reply failed, received unexpected launch message", > + "guestfs_umask"); > + guestfs_end_busy (g); > + return -1; > + } > + > + if (0 == reply.len) { > + error (g, "%s reply failed, see earlier error messages", "guestfs_umask"); > + guestfs_end_busy (g); > + return -1; > + } > + > + break; > } > > - if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_UMASK, serial) == -1) { > - guestfs_end_busy (g); > - return -1; > + if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) { > + error (g, "%s: failed to parse reply header", "guestfs_umask"); > + goto recv_error; > } > > - if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { > - error (g, "%s", ctx.err.error_message); > - free (ctx.err.error_message); > - guestfs_end_busy (g); > - return -1; > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + if (!xdr_guestfs_message_error (&reply.xdr, &err)) { > + error (g, "%s: failed to parse reply error", "guestfs_umask"); > + goto recv_error; > + } > + } > + else if (!xdr_guestfs_umask_ret (&reply.xdr, &ret)) { > + error (g, "%s: failed to parse reply", "guestfs_umask"); > + goto recv_error; > + } > + if (check_reply_header (g, &hdr, GUESTFS_PROC_UMASK, serial) == -1) { > + goto recv_error; > + } > + > + if (hdr.status == GUESTFS_STATUS_ERROR) { > + error (g, "%s", err.error_message); > + free (err.error_message); > + goto recv_error; > } > > + guestfs_free_reply (g, &reply); > + > + guestfs_end_busy (g); > + > + return ret.oldmask; > + > + recv_error: > + guestfs_free_reply (g, &reply); > guestfs_end_busy (g); > - return ctx.ret.oldmask; > + return -1; > } > > diff --git a/src/guestfs.c b/src/guestfs.c > index 2d4db66..6f4c83e 100644 > --- a/src/guestfs.c > +++ b/src/guestfs.c > @@ -21,6 +21,7 @@ > #define _BSD_SOURCE /* for mkdtemp, usleep */ > #define _GNU_SOURCE /* for vasprintf, GNU strerror_r, strchrnul */ > > +#include > #include > #include > #include > @@ -77,8 +78,10 @@ > > static void default_error_cb (guestfs_h *g, void *data, const char *msg);> > static void stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > -static void sock_read_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > -static void sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > +static void sock_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > +static void sock_read (guestfs_h *g); > +static void sock_write (guestfs_h *g); > +static int sock_update_events (guestfs_h *g); > > static void close_handles (void); > > @@ -160,6 +163,9 @@ struct guestfs_h > int stdout_watch; /* Watches qemu stdout for log messages. */ > int sock_watch; /* Watches daemon comm socket. */ > > + int sock_events; /* events we're listening for on the comm > + socket */ > + > char *tmpdir; /* Temporary directory containing socket. */ > > char *qemu_help, *qemu_version; /* Output of qemu -help, qemu -version. */ > @@ -184,21 +190,18 @@ struct guestfs_h > void * error_cb_data; > guestfs_send_cb send_cb; > void * send_cb_data; > - guestfs_reply_cb reply_cb; > - void * reply_cb_data; > guestfs_log_message_cb log_message_cb; > void * log_message_cb_data; > guestfs_subprocess_quit_cb subprocess_quit_cb; > void * subprocess_quit_cb_data; > - guestfs_launch_done_cb launch_done_cb; > - void * launch_done_cb_data; > > /* Main loop used by this handle. */ > guestfs_main_loop *main_loop; > > /* Messages sent and received from the daemon. */ > char *msg_in; > - int msg_in_size, msg_in_allocated; > + size_t msg_in_size, msg_in_pos, msg_in_consumed, msg_in_len; > + > char *msg_out; > int msg_out_size, msg_out_pos; > > @@ -227,6 +230,8 @@ guestfs_create (void) > g->stdout_watch = -1; > g->sock_watch = -1; > > + g->sock_events = 0; > + > g->abort_cb = abort; > g->error_cb = default_error_cb; > g->error_cb_data = NULL; > @@ -264,6 +269,11 @@ guestfs_create (void) > } else > g->memsize = 500; > > + /* Initialise the message receive buffer */ > + g->msg_in_size = GUESTFS_MESSAGE_MAX + sizeof (g->msg_in_len); The size of the length word is always 4 bytes - it's defined that way in the XDR standard. > + g->msg_in = safe_malloc (g, g->msg_in_size); > + g->msg_in_pos = g->msg_in_consumed = 0; > + > g->main_loop = guestfs_get_default_main_loop (); > > /* Start with large serial numbers so they are easy to spot > @@ -289,9 +299,10 @@ guestfs_create (void) > return g; > > error: > - free (g->path); > - free (g->qemu); > - free (g->append); > + if (g->msg_in) free (g->msg_in); > + if (g->path) free (g->path); > + if (g->qemu) free (g->qemu); > + if (g->append) free (g->append); This is wrong. free (NULL) is always correct, so we just need to do: free (g->msg_in); etc. (without the 'if'). > free (g); > return NULL; > } > @@ -1122,10 +1133,6 @@ guestfs_launch (guestfs_h *g) > > connected: > /* Watch the file descriptors. */ > - free (g->msg_in); > - g->msg_in = NULL; > - g->msg_in_size = g->msg_in_allocated = 0; > - > free (g->msg_out); > g->msg_out = NULL; > g->msg_out_size = 0; > @@ -1140,7 +1147,9 @@ guestfs_launch (guestfs_h *g) > goto cleanup3; > } > > - if (guestfs__switch_to_receiving (g) == -1) > + g->sock_events = GUESTFS_HANDLE_READABLE | > + GUESTFS_HANDLE_ERROR | GUESTFS_HANDLE_HANGUP; > + if (sock_update_events (g) == -1) > goto cleanup3; > > g->state = LAUNCHING; > @@ -1298,20 +1307,10 @@ qemu_supports (guestfs_h *g, const char *option) > return g->qemu_help && strstr (g->qemu_help, option) != NULL; > } > > -static void > -finish_wait_ready (guestfs_h *g, void *vp) > -{ > - if (g->verbose) > - fprintf (stderr, "finish_wait_ready called, %p, vp = %p\n", g, vp); > - > - *((int *)vp) = 1; > - g->main_loop->main_loop_quit (g->main_loop, g); > -} > - > int > guestfs_wait_ready (guestfs_h *g) > { > - int finished = 0, r; > + guestfs_reply_t reply = {}; > > if (g->state == READY) return 0; > > @@ -1325,29 +1324,29 @@ guestfs_wait_ready (guestfs_h *g) > return -1; > } > > - g->launch_done_cb = finish_wait_ready; > - g->launch_done_cb_data = &finished; > - r = g->main_loop->main_loop_run (g->main_loop, g); > - g->launch_done_cb = NULL; > - g->launch_done_cb_data = NULL; > - > - if (r == -1) return -1; > - > - if (finished != 1) { > - error (g, _("guestfs_wait_ready failed, see earlier error messages")); > + guestfs_get_reply (g, &reply, 1); > + if (0 == reply.len) { > + error (g, _("guestfs_wait_ready: error receiving reply")); > + return -1; > + } This convention for indicating errors is a little odd. Why doesn't guestfs_get_reply return 0 / -1 ? > + if (GUESTFS_LAUNCH_FLAG != reply.len) { > + error (g, _("guestfs_wait_ready: received non-launch reply")); > return -1; > } > + guestfs_free_reply (g, &reply); Does this leak the reply message on the error path? > /* This is possible in some really strange situations, such as > * guestfsd starts up OK but then qemu immediately exits. Check for > * it because the caller is probably expecting to be able to send > * commands after this function returns. > */ > - if (g->state != READY) { > - error (g, _("qemu launched and contacted daemon, but state != READY")); > + if (g->state != LAUNCHING) { > + error (g, _("qemu launched and contacted daemon, but state != LAUNCHING")); > return -1; > } > > + g->state = READY; > + > return 0; > } > > @@ -1473,7 +1472,7 @@ guestfs_free_lvm_lv_list (struct guestfs_lvm_lv_list *x) > free (x); > } > > -/* We don't know if stdout_event or sock_read_event will be the > +/* We don't know if stdout_event or sock_read will be the > * first to receive EOF if the qemu process dies. This function > * has the common cleanup code for both. > */ > @@ -1551,175 +1550,218 @@ stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > g->log_message_cb (g, g->log_message_cb_data, buf, n); > } > > -/* The function is called whenever we can read something on the > - * guestfsd (daemon inside the guest) communication socket. > - */ > -static void > -sock_read_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > - int watch, int fd, int events) > +void > +guestfs_get_reply (guestfs_h *g, guestfs_reply_t *msg, > + unsigned char blocking) > { > - XDR xdr; > - u_int32_t len; > - int n; > + msg->len = 0; > > - if (g->verbose) > - fprintf (stderr, > - "sock_read_event: %p g->state = %d, fd = %d, events = 0x%x\n", > - g, g->state, fd, events); > - > - if (g->sock != fd) { > - error (g, _("sock_read_event: internal error: %d != %d"), g->sock, fd); > + /* Not in the expected state. */ > + if (g->state != BUSY && g->state != LAUNCHING) { > + error (g, _("state %d != BUSY && g->state != LAUNCHING"), g->state); > return; > } > > - if (g->msg_in_size <= g->msg_in_allocated) { > - g->msg_in_allocated += 4096; > - g->msg_in = safe_realloc (g, g->msg_in, g->msg_in_allocated); > + /* Execute the main loop until we've received at least 1 complete message */ > + for (;;) { > + struct guestfs_main_loop *ml = guestfs_get_main_loop(g); > + > + size_t available = g->msg_in_pos - g->msg_in_consumed; > + > + if (available >= sizeof (g->msg_in_len)) { As above, I think you mean '>= 4' here. And also some places below too. > + xdrmem_create (&msg->xdr, g->msg_in + g->msg_in_consumed, > + g->msg_in_pos - g->msg_in_consumed, XDR_DECODE); > + > + /* Read the message length */ > + if (!xdr_uint32_t (&msg->xdr, &g->msg_in_len)) { > + error (g, _("can't decode length")); > + xdr_destroy(&msg->xdr); > + return; > + } > + > + if (g->verbose) { > + fprintf(stderr, "message length is %u\n", g->msg_in_len); > + } > + > + /* Special cases for messages which are represented by magic message > + * lengths */ > + if (GUESTFS_LAUNCH_FLAG == g->msg_in_len || > + GUESTFS_CANCEL_FLAG == g->msg_in_len) { > + msg->len = g->msg_in_len; > + g->msg_in_len = sizeof(g->msg_in_len); > + break; > + } > + > + else if (g->msg_in_len > GUESTFS_MESSAGE_MAX) { > + error (g, _("message length (%u) > maximum possible size (%d)"), > + g->msg_in_len, GUESTFS_MESSAGE_MAX); > + /* We're doomed at this point. */ > + abort(); > + } > + > + /* Quit the loop if we've got a complete message */ > + else if (available >= g->msg_in_len + sizeof (g->msg_in_len)) { > + /* Total message length includes the length header itself */ > + g->msg_in_len += sizeof (g->msg_in_len); > + msg->len = g->msg_in_len; > + break; > + } > + > + xdr_destroy (&msg->xdr); > + } > + > + if(!blocking) return; > + > + ml->main_loop_run (ml, g); > } > - n = read (g->sock, g->msg_in + g->msg_in_size, > - g->msg_in_allocated - g->msg_in_size); > - if (n == 0) { > - /* Disconnected. */ > - child_cleanup (g); > - return; > +} > + > +void > +guestfs_free_reply (guestfs_h *g, guestfs_reply_t *msg) > +{ > + /* Check that the whole message has been consumed */ > + if (g->msg_in_len != xdr_getpos(&msg->xdr)) { > + error (g, _("guestfs_free_reply: consumed %u bytes of %u length message"), > + xdr_getpos(&msg->xdr), g->msg_in_len); > } > > - if (n == -1) { > - if (errno != EINTR && errno != EAGAIN) > - perrorf (g, "read"); > - return; > + xdr_destroy (&msg->xdr); > + > + g->msg_in_consumed += g->msg_in_len; > + > + if (g->verbose) { > + fprintf (stderr, "guestfs_free_reply: consumed %u bytes\n", > + g->msg_in_consumed); > } > > - g->msg_in_size += n; > + /* If there's nothing left in the buffer, reset to the beginning */ > + if (g->msg_in_consumed == g->msg_in_pos) { > + g->msg_in_consumed = 0; > + g->msg_in_pos = 0; > + } > > - /* Have we got enough of a message to be able to process it yet? */ > - again: > - if (g->msg_in_size < 4) return; > + /* If we got to the end of the buffer, move to the beginning */ > + else if (g->msg_in_size == g->msg_in_pos) { > + memmove (g->msg_in, g->msg_in + g->msg_in_consumed, > + g->msg_in_size - g->msg_in_consumed); > + g->msg_in_pos = g->msg_in_size - g->msg_in_consumed; > + g->msg_in_consumed = 0; > + } > + > + g->msg_in_len = 0; > > - xdrmem_create (&xdr, g->msg_in, g->msg_in_size, XDR_DECODE); > - if (!xdr_uint32_t (&xdr, &len)) { > - error (g, _("can't decode length word")); > - goto cleanup; > + /* If we were ignoring incoming messages, switch them back on */ > + if (!(g->sock_events & GUESTFS_HANDLE_READABLE)) { > + g->sock_events |= GUESTFS_HANDLE_READABLE; > + sock_update_events (g); > } > +} > > - /* Length is normally the length of the message, but when guestfsd > - * starts up it sends a "magic" value (longer than any possible > - * message). Check for this. > - */ > - if (len == GUESTFS_LAUNCH_FLAG) { > - if (g->state != LAUNCHING) > - error (g, _("received magic signature from guestfsd, but in state %d"), > - g->state); > - else if (g->msg_in_size != 4) > - error (g, _("received magic signature from guestfsd, but msg size is %d"), > - g->msg_in_size); > - else { > - g->state = READY; > - if (g->launch_done_cb) > - g->launch_done_cb (g, g->launch_done_cb_data); > - } > +/* This function is called whenever an event happens on the communications > + * socket */ > +static void > +sock_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > + int watch, int fd, int events) > +{ > + if (g->verbose) > + fprintf (stderr, > + "sock_event: %p g->state = %d, fd = %d, events = 0x%x\n", > + g, g->state, fd, events); > > - goto cleanup; > + if (fd != g->sock) { > + error (g, _("sock_event: received event for non-sock fd %d"), fd); > + return; > } > > - /* This can happen if a cancellation happens right at the end > - * of us sending a FileIn parameter to the daemon. Discard. The > - * daemon should send us an error message next. > - */ > - if (len == GUESTFS_CANCEL_FLAG) { > - g->msg_in_size -= 4; > - memmove (g->msg_in, g->msg_in+4, g->msg_in_size); > - goto again; > + if (events & GUESTFS_HANDLE_READABLE) { > + sock_read (g); > } > > - /* If this happens, it's pretty bad and we've probably lost > - * synchronization. > - */ > - if (len > GUESTFS_MESSAGE_MAX) { > - error (g, _("message length (%u) > maximum possible size (%d)"), > - len, GUESTFS_MESSAGE_MAX); > - goto cleanup; > + if (events & GUESTFS_HANDLE_WRITABLE) { > + sock_write (g); > } > > - if (g->msg_in_size-4 < len) return; /* Need more of this message. */ > + if (events & (GUESTFS_HANDLE_ERROR | GUESTFS_HANDLE_HANGUP)) { > + error (g, _("sock_event: received error on communications socket: %m")); > + child_cleanup (g); > + } > +} > > - /* Got the full message, begin processing it. */ > -#if 0 > - if (g->verbose) { > - int i, j; > - > - for (i = 0; i < g->msg_in_size; i += 16) { > - printf ("%04x: ", i); > - for (j = i; j < MIN (i+16, g->msg_in_size); ++j) > - printf ("%02x ", (unsigned char) g->msg_in[j]); > - for (; j < i+16; ++j) > - printf (" "); > - printf ("|"); > - for (j = i; j < MIN (i+16, g->msg_in_size); ++j) > - if (isprint (g->msg_in[j])) > - printf ("%c", g->msg_in[j]); > - else > - printf ("."); > - for (; j < i+16; ++j) > - printf (" "); > - printf ("|\n"); > +/* This function reads as much data as is available from the guestfsd > + * communication socket. > + */ > +static void > +sock_read (guestfs_h *g) > +{ > + guestfs_main_loop *ml = guestfs_get_main_loop (g); > + > + size_t available = g->msg_in_size - g->msg_in_pos; > + > + if (g->verbose) > + fprintf (stderr, "sock_read: before g->msg_in_pos = %d " > + "available = %d\n", g->msg_in_pos, available); > + > + while (available > 0) { > + ssize_t in; > + while((in = read(g->sock, g->msg_in + g->msg_in_pos, available)) < 0) { > + /* Retry if interrupted */ > + if(EINTR == errno) continue; > + > + if(EWOULDBLOCK != errno) { > + error (g, _("sock_read_data: error reading from socket: %s"), > + strerror(errno)); > + } > + > + break; > + } > + > + /* Cleanup if we got an EOF */ > + if (0 == in) { > + child_cleanup(g); > + return; > + } > + > + /* We got data */ > + else if (in > 0) { > + available -= in; > + g->msg_in_pos += in; > + } > + > + /* There was some error */ > + else { > + break; > } > } > -#endif > > - /* Not in the expected state. */ > - if (g->state != BUSY) > - error (g, _("state %d != BUSY"), g->state); > - > - /* Push the message up to the higher layer. */ > - if (g->reply_cb) > - g->reply_cb (g, g->reply_cb_data, &xdr); > - else > - /* This message (probably) should never be printed. */ > - fprintf (stderr, "libguesfs: sock_read_event: !!! dropped message !!!\n"); > - > - g->msg_in_size -= len + 4; > - memmove (g->msg_in, g->msg_in+len+4, g->msg_in_size); > - if (g->msg_in_size > 0) goto again; > - > - cleanup: > - /* Free the message buffer if it's grown excessively large. */ > - if (g->msg_in_allocated > 65536) { > - free (g->msg_in); > - g->msg_in = NULL; > - g->msg_in_size = g->msg_in_allocated = 0; > - } else > - g->msg_in_size = 0; > + if (g->verbose) > + fprintf (stderr, "sock_read: after g->msg_in_pos = %d " > + "available = %d\n", g->msg_in_pos, available); > > - xdr_destroy (&xdr); > + /* Ignore further read events if we've filled the buffer */ > + if (0 == available) { > + g->sock_events &= ~GUESTFS_HANDLE_READABLE; > + sock_update_events (g); > + } > + > + /* Exit the main loop to give the caller a chance to pick up the message */ > + ml->main_loop_quit (ml, g); > } > > /* The function is called whenever we can write something on the > * guestfsd (daemon inside the guest) communication socket. > */ > static void > -sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > - int watch, int fd, int events) > +sock_write (guestfs_h *g) > { > int n, err; > > - if (g->verbose) > - fprintf (stderr, > - "sock_write_event: %p g->state = %d, fd = %d, events = 0x%x\n", > - g, g->state, fd, events); > - > - if (g->sock != fd) { > - error (g, _("sock_write_event: internal error: %d != %d"), g->sock, fd); > - return; > - } > - > if (g->state != BUSY) { > - error (g, _("sock_write_event: state %d != BUSY"), g->state); > + error (g, _("sock_write: state %d != BUSY"), g->state); > return; > } > > if (g->verbose) > - fprintf (stderr, "sock_write_event: writing %d bytes ...\n", > + fprintf (stderr, "sock_write: writing %d bytes ...\n", > g->msg_out_size - g->msg_out_pos); > > n = write (g->sock, g->msg_out + g->msg_out_pos, > @@ -1734,7 +1776,7 @@ sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > } > > if (g->verbose) > - fprintf (stderr, "sock_write_event: wrote %d bytes\n", n); > + fprintf (stderr, "sock_write: wrote %d bytes\n", n); > > g->msg_out_pos += n; > > @@ -1743,7 +1785,7 @@ sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, > return; > > if (g->verbose) > - fprintf (stderr, "sock_write_event: done writing, calling send_cb\n"); > + fprintf (stderr, "sock_write: done writing, calling send_cb\n"); > > free (g->msg_out); > g->msg_out = NULL; > @@ -1763,14 +1805,6 @@ guestfs_set_send_callback (guestfs_h *g, > } > > void > -guestfs_set_reply_callback (guestfs_h *g, > - guestfs_reply_cb cb, void *opaque) > -{ > - g->reply_cb = cb; > - g->reply_cb_data = opaque; > -} > - > -void > guestfs_set_log_message_callback (guestfs_h *g, > guestfs_log_message_cb cb, void *opaque) > { > @@ -1786,14 +1820,6 @@ guestfs_set_subprocess_quit_callback (guestfs_h *g, > g->subprocess_quit_cb_data = opaque; > } > > -void > -guestfs_set_launch_done_callback (guestfs_h *g, > - guestfs_launch_done_cb cb, void *opaque) > -{ > - g->launch_done_cb = cb; > - g->launch_done_cb_data = opaque; > -} > - > /* Access to the handle's main loop and the default main loop. */ > void > guestfs_set_main_loop (guestfs_h *g, guestfs_main_loop *main_loop) > @@ -1813,35 +1839,15 @@ guestfs_get_default_main_loop (void) > return (guestfs_main_loop *) &default_main_loop; > } > > -/* Change the daemon socket handler so that we are now writing. > - * This sets the handle to sock_write_event. > +/* Update the events which will cause the daemon socket callback to be called. > */ > -int > -guestfs__switch_to_sending (guestfs_h *g) > +static int > +sock_update_events (guestfs_h *g) > { > - if (g->sock_watch >= 0) { > - if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) { > - error (g, _("remove_handle failed")); > - g->sock_watch = -1; > - return -1; > - } > - } > - > - g->sock_watch = > - g->main_loop->add_handle (g->main_loop, g, g->sock, > - GUESTFS_HANDLE_WRITABLE, > - sock_write_event, NULL); > - if (g->sock_watch == -1) { > - error (g, _("add_handle failed")); > - return -1; > + if(g->verbose) { > + fprintf(stderr, "updating socket events to %d\n", g->sock_events); > } > > - return 0; > -} > - > -int > -guestfs__switch_to_receiving (guestfs_h *g) > -{ > if (g->sock_watch >= 0) { > if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) { > error (g, _("remove_handle failed")); > @@ -1852,8 +1858,8 @@ guestfs__switch_to_receiving (guestfs_h *g) > > g->sock_watch = > g->main_loop->add_handle (g->main_loop, g, g->sock, > - GUESTFS_HANDLE_READABLE, > - sock_read_event, NULL); > + g->sock_events, > + sock_event, NULL); > if (g->sock_watch == -1) { > error (g, _("add_handle failed")); > return -1; > @@ -1945,7 +1951,9 @@ guestfs__send_sync (guestfs_h *g, int proc_nr, > xdrmem_create (&xdr, g->msg_out, 4, XDR_ENCODE); > xdr_uint32_t (&xdr, &len); > > - if (guestfs__switch_to_sending (g) == -1) > + /* Respond to writable events */ > + g->sock_events |= GUESTFS_HANDLE_WRITABLE; > + if (sock_update_events (g) == -1) > goto cleanup1; > > sent = 0; > @@ -1957,6 +1965,13 @@ guestfs__send_sync (guestfs_h *g, int proc_nr, > goto cleanup1; > } > > + /* No longer interested in writable events */ > + g->sock_events &= ~(GUESTFS_HANDLE_WRITABLE); > + if (sock_update_events (g) == -1) { > + error (g, _("guestfs__send_sync: " > + "failed to remove socket writable callback\n")); > + } > + > return serial; > > cleanup1: > @@ -2056,8 +2071,6 @@ send_file_complete_sync (guestfs_h *g) > /* Send a chunk, cancellation or end of file, synchronously (ie. wait > * for it to go). > */ > -static int check_for_daemon_cancellation (guestfs_h *g); > - > static int > send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > { > @@ -2067,6 +2080,8 @@ send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > XDR xdr; > guestfs_main_loop *ml = guestfs_get_main_loop (g); > > + guestfs_reply_t cancellation = {}; > + > if (g->state != BUSY) { > error (g, _("send_file_chunk_sync: state %d != READY"), g->state); > return -1; > @@ -2081,11 +2096,15 @@ send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > } > > /* Did the daemon send a cancellation message? */ > - if (check_for_daemon_cancellation (g)) { > + guestfs_get_reply (g, &cancellation, 0); > + if (GUESTFS_CANCEL_FLAG == cancellation.len) { > if (g->verbose) > fprintf (stderr, "got daemon cancellation\n"); > return -2; > } > + if (0 != cancellation.len) { > + guestfs_free_reply (g, &cancellation); > + } > > /* Allocate the chunk buffer. Don't use the stack to avoid > * excessive stack usage and unnecessary copies. > @@ -2116,7 +2135,9 @@ send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > xdrmem_create (&xdr, g->msg_out, 4, XDR_ENCODE); > xdr_uint32_t (&xdr, &len); > > - if (guestfs__switch_to_sending (g) == -1) > + /* Respond to socket writable events */ > + g->sock_events |= GUESTFS_HANDLE_WRITABLE; > + if (sock_update_events (g) == -1) > goto cleanup1; > > sent = 0; > @@ -2128,6 +2149,12 @@ send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > goto cleanup1; > } > > + g->sock_events &= ~(GUESTFS_HANDLE_WRITABLE); > + if (sock_update_events (g) == -1) { > + error (g, _("send_file_chunk_sync: " > + "failed to remove socket writable callback\n")); > + } > + > return 0; > > cleanup1: > @@ -2137,52 +2164,6 @@ send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t buflen) > return -1; > } > > -/* At this point we are sending FileIn file(s) to the guest, and not > - * expecting to read anything, so if we do read anything, it must be > - * a cancellation message. This checks for this case without blocking. > - */ > -static int > -check_for_daemon_cancellation (guestfs_h *g) > -{ > - fd_set rset; > - struct timeval tv; > - int r; > - char buf[4]; > - uint32_t flag; > - XDR xdr; > - > - FD_ZERO (&rset); > - FD_SET (g->sock, &rset); > - tv.tv_sec = 0; > - tv.tv_usec = 0; > - r = select (g->sock+1, &rset, NULL, NULL, &tv); > - if (r == -1) { > - perrorf (g, "select"); > - return 0; > - } > - if (r == 0) > - return 0; > - > - /* Read the message from the daemon. */ > - r = xread (g->sock, buf, sizeof buf); > - if (r == -1) { > - perrorf (g, "read"); > - return 0; > - } > - > - xdrmem_create (&xdr, buf, sizeof buf, XDR_DECODE); > - xdr_uint32_t (&xdr, &flag); > - xdr_destroy (&xdr); > - > - if (flag != GUESTFS_CANCEL_FLAG) { > - error (g, _("check_for_daemon_cancellation: read 0x%x from daemon, expected 0x%x\n"), > - flag, GUESTFS_CANCEL_FLAG); > - return 0; > - } > - > - return 1; > -} > - > /* Synchronously receive a file. */ > > /* Returns -1 = error, 0 = EOF, 1 = more data */ > @@ -2194,6 +2175,7 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) > void *buf; > int fd, r; > size_t len; > + size_t total_bytes = 0, total_receives = 0; > > fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666); > if (fd == -1) { > @@ -2203,6 +2185,11 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) > > /* Receive the file in chunked encoding. */ > while ((r = receive_file_data_sync (g, &buf, &len)) >= 0) { > + if (g->verbose) { > + fprintf(stderr, "guestfs__receive_file_sync: " > + "writing %zi bytes to %s\n", len, filename); > + } > + > if (xwrite (fd, buf, len) == -1) { > perrorf (g, "%s: write", filename); > free (buf); > @@ -2210,6 +2197,9 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) > } > free (buf); > if (r == 0) break; /* End of file. */ > + > + total_bytes += len; > + total_receives++; > } > > if (r == -1) { > @@ -2222,6 +2212,12 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) > return -1; > } > > + if (g->verbose) { > + fprintf(stderr, "guestfs__receive_file_sync: " > + "wrote %zi bytes in %zi calls to %s\n", > + total_bytes, total_receives, filename); > + } > + > return 0; > > cancel: ; > @@ -2247,117 +2243,75 @@ guestfs__receive_file_sync (guestfs_h *g, const char *filename) > return -1; > } > > -/* Note that the reply callback can be called multiple times before > - * the main loop quits and we get back to the synchronous code. So > - * we have to be prepared to save multiple chunks on a list here. > - */ > -struct receive_file_ctx { > - int count; /* 0 if receive_file_cb not called, or > - * else count number of chunks. > - */ > - guestfs_chunk *chunks; /* Array of chunks. */ > -}; > - > -static void > -free_chunks (struct receive_file_ctx *ctx) > -{ > - int i; > - > - for (i = 0; i < ctx->count; ++i) > - free (ctx->chunks[i].data.data_val); > - > - free (ctx->chunks); > -} > - > -static void > -receive_file_cb (guestfs_h *g, void *data, XDR *xdr) > -{ > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - struct receive_file_ctx *ctx = (struct receive_file_ctx *) data; > - guestfs_chunk chunk; > - > - if (ctx->count == -1) /* Parse error occurred previously. */ > - return; > - > - ml->main_loop_quit (ml, g); > - > - memset (&chunk, 0, sizeof chunk); > - > - if (!xdr_guestfs_chunk (xdr, &chunk)) { > - error (g, _("failed to parse file chunk")); > - free_chunks (ctx); > - ctx->chunks = NULL; > - ctx->count = -1; > - return; > - } > - > - /* Copy the chunk to the list. */ > - ctx->chunks = safe_realloc (g, ctx->chunks, > - sizeof (guestfs_chunk) * (ctx->count+1)); > - ctx->chunks[ctx->count] = chunk; > - ctx->count++; > -} > - > /* Receive a chunk of file data. */ > /* Returns -1 = error, 0 = EOF, 1 = more data */ > static int > -receive_file_data_sync (guestfs_h *g, void **buf, size_t *len_r) > +receive_file_data_sync (guestfs_h *g, void **buf, size_t *len) > { > - struct receive_file_ctx ctx; > - guestfs_main_loop *ml = guestfs_get_main_loop (g); > - int i; > - size_t len; > + unsigned char block = 1; > > - ctx.count = 0; > - ctx.chunks = NULL; > + /* Accumulate data in this buffer. */ > + if (buf) *buf = NULL; > + if (len) *len = 0; > > - guestfs_set_reply_callback (g, receive_file_cb, &ctx); > - (void) ml->main_loop_run (ml, g); > - guestfs_set_reply_callback (g, NULL, NULL); > + /* Buffer chunks until one of: > + * There are no more immediately available > + * The buffer got too big > + * We got the last chunk > + */ > + for(;;) { > + guestfs_reply_t reply; > + guestfs_chunk chunk; > + > + /* Get a reply message if there's one available */ > + guestfs_get_reply (g, &reply, block); > + > + /* No more replies available right now */ > + if (0 == reply.len) { > + /* We should have waited until we got at least 1 */ > + if (NULL == *buf) { > + error (g, _("receive_file_data: error receiving chunk")); > + guestfs_free_reply (g, &reply); > + return -1; > + } > > - if (ctx.count == 0) { > - error (g, _("receive_file_data_sync: reply callback not called\n")); > - return -1; > - } > + break; > + } > > - if (ctx.count == -1) { > - error (g, _("receive_file_data_sync: parse error in reply callback\n")); > - /* callback already freed the chunks */ > - return -1; > - } > + if (g->verbose) > + fprintf (stderr, "receive_file_data_sync: got chunk\n"); > + > + memset (&chunk, 0, sizeof (chunk)); > > - if (g->verbose) > - fprintf (stderr, "receive_file_data_sync: got %d chunks\n", ctx.count); > - > - /* Process each chunk in the list. */ > - if (buf) *buf = NULL; /* Accumulate data in this buffer. */ > - len = 0; > - > - for (i = 0; i < ctx.count; ++i) { > - if (ctx.chunks[i].cancel) { > - error (g, _("file receive cancelled by daemon")); > - free_chunks (&ctx); > - if (buf) free (*buf); > - if (len_r) *len_r = 0; > + if (!xdr_guestfs_chunk (&reply.xdr, &chunk)) { > + error (g, _("receive_file_data_sync: failed to parse file chunk")); > + guestfs_free_reply (g, &reply); > return -1; > } > > - if (ctx.chunks[i].data.data_len == 0) { /* end of transfer */ > - free_chunks (&ctx); > - if (len_r) *len_r = len; > + /* Copy the chunk into the output buffer */ > + if (len && buf) { > + *buf = safe_realloc (g, *buf, *len + chunk.data.data_len); > + memcpy (*buf + *len, chunk.data.data_val, chunk.data.data_len); > + *len += chunk.data.data_len; > + } > + > + guestfs_free_reply (g, &reply); > + > + /* Received the last chunk */ > + if (0 == chunk.data.data_len) { > return 0; > } > > - if (buf) { > - *buf = safe_realloc (g, *buf, len + ctx.chunks[i].data.data_len); > - memcpy (*buf+len, ctx.chunks[i].data.data_val, > - ctx.chunks[i].data.data_len); > + /* Return early if the the output buffer length is bigger than some > + * arbitrary size. Note that the output buffer may exceed this size. */ > + if (len && *len > 1024 * 1024) { > + break; > } > - len += ctx.chunks[i].data.data_len; > + > + block = 0; > } > > - if (len_r) *len_r = len; > - free_chunks (&ctx); > return 1; > } The way git has formatted this patch makes it really hard to follow what has changed ... > diff --git a/src/guestfs.h b/src/guestfs.h > index b5ed0f7..018183d 100644 > --- a/src/guestfs.h > +++ b/src/guestfs.h > @@ -63,13 +63,10 @@ typedef void (*guestfs_send_cb) (guestfs_h *g, void *data); > typedef void (*guestfs_reply_cb) (guestfs_h *g, void *data, XDR *xdr); > typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *data, char *buf, int len); > typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *data); > -typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *data); > > extern void guestfs_set_send_callback (guestfs_h *g, guestfs_send_cb cb, void *opaque); > -extern void guestfs_set_reply_callback (guestfs_h *g, guestfs_reply_cb cb, void *opaque); > extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque); > extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque); > -extern void guestfs_set_launch_done_callback (guestfs_h *g, guestfs_launch_done_cb cb, void *opaque); > > extern void guestfs_error (guestfs_h *g, const char *fs, ...) > __attribute__((format (printf,2,3))); > @@ -80,8 +77,14 @@ extern void *guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes); > extern char *guestfs_safe_strdup (guestfs_h *g, const char *str); > extern void *guestfs_safe_memdup (guestfs_h *g, void *ptr, size_t size); > > -extern int guestfs__switch_to_sending (guestfs_h *g); > -extern int guestfs__switch_to_receiving (guestfs_h *g); > +typedef struct { > + u_int32_t len; > + XDR xdr; > +} guestfs_reply_t; > + > +extern void guestfs_get_reply (guestfs_h *g, guestfs_reply_t *msg, > + unsigned char blocking); > +extern void guestfs_free_reply (guestfs_h *g, guestfs_reply_t *msg); > > /* These *_sync calls wait until the action is performed, using the > * main loop. We should implement asynchronous versions too. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From agx at sigxcpu.org Thu Jul 2 11:15:59 2009 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Thu, 2 Jul 2009 13:15:59 +0200 Subject: [fedora-virt] [PATCH] allow to build Debian based appliance Message-ID: <20090702111559.GA24243@bogon.sigxcpu.org> Hi, the attached 4 patches allow to build the appliance based on Debian based distros: 0001-add-missing-module.patch: one more missing module from the kmod whitelist 0002-unconditionally-load-dm-module.patch: I do need to load this one to get LVM/device mapper stuff working 0003-add-debirf-files.patch uses debirf to build the initramfs 0004-Build-Debian-based-appliance-using-debirf.patch update {make,update}.sh (best reviewed with diff -w) If built with: ./configure --with-repo=sid --with-mirror=http://ftp.debian.org/debian The testsuite looks mostly good. ***** 5 / 174 tests FAILED ***** Failures are due to missing srub in Debian as well as a 2 hexdump failures I'll have to look at. Cheers, -- Guido -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-add-missing-module.patch Type: text/x-diff Size: 593 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-unconditionally-load-dm-module.patch Type: text/x-diff Size: 603 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-add-debirf-files.patch Type: text/x-diff Size: 8749 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0004-Build-Debian-based-appliance-using-debirf.patch Type: text/x-diff Size: 9891 bytes Desc: not available URL: From jim at meyering.net Thu Jul 2 11:32:01 2009 From: jim at meyering.net (Jim Meyering) Date: Thu, 02 Jul 2009 13:32:01 +0200 Subject: [fedora-virt] [PATCH] arrange to build some generated sources Message-ID: <874otvuxqm.fsf@meyering.net> Hi Rich, I've just pulled the latest, and then ran this: git clean -x -d -f && ./autogen.sh First problem was this: *** No rule to make target `guestfs-structs.h' I worked around it with the patch below, but then got this: libtool: link: CURRENT `' must be a nonnegative integer libtool: link: `:0:' is not valid version information make[3]: *** [libguestfs.la] Error 1 >From 82ae736bb0ddcec56a4a6e756b3064c6548724fb Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 2 Jul 2009 13:30:07 +0200 Subject: [PATCH] arrange to build some generated sources * src/Makefile.am (BUILT_SOURCES): Define. ($(BUILT_SOURCES)): Depend on stamp-generator. --- src/Makefile.am | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index eb8723a..1c0fa0a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,15 @@ lib_LTLIBRARIES = libguestfs.la # Note that this scheme means the real library version will always be # 'libguestfs.so.0.$(MAX_PROC_NR).0'. +BUILT_SOURCES = \ + guestfs_protocol.x \ + guestfs-structs.h \ + guestfs-actions.h \ + guestfs-actions.c \ + guestfs-bindtests.c + +$(BUILT_SOURCES): stamp-generator + libguestfs_la_LDFLAGS = -version-info $(MAX_PROC_NR):0:$(MAX_PROC_NR) libguestfs_la_SOURCES = \ guestfs.c \ -- 1.6.3.3.507.gc6b5a From rjones at redhat.com Thu Jul 2 12:16:13 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 13:16:13 +0100 Subject: [fedora-virt] Re: [PATCH] allow to build Debian based appliance In-Reply-To: <20090702111559.GA24243@bogon.sigxcpu.org> References: <20090702111559.GA24243@bogon.sigxcpu.org> Message-ID: <20090702121613.GB22036@amd.home.annexia.org> On Thu, Jul 02, 2009 at 01:15:59PM +0200, Guido G?nther wrote: > Hi, > the attached 4 patches allow to build the appliance based on Debian > based distros: > > 0001-add-missing-module.patch: > one more missing module from the kmod whitelist > 0002-unconditionally-load-dm-module.patch: > I do need to load this one to get LVM/device mapper stuff working > 0003-add-debirf-files.patch > uses debirf to build the initramfs > 0004-Build-Debian-based-appliance-using-debirf.patch > update {make,update}.sh (best reviewed with diff -w) > > If built with: > > ./configure --with-repo=sid --with-mirror=http://ftp.debian.org/debian > > The testsuite looks mostly good. > > ***** 5 / 174 tests FAILED ***** > > Failures are due to missing srub in Debian as well as a 2 hexdump > failures I'll have to look at. > > Cheers, > -- Guido > >From 65aca909131ec53da4032a727e1fd346b6bb7401 Mon Sep 17 00:00:00 2001 > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Tue, 30 Jun 2009 14:44:09 +0200 > Subject: [PATCH 1/4] add missing module > > for modularized Debian kernels > --- > appliance/kmod.whitelist.in | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/appliance/kmod.whitelist.in b/appliance/kmod.whitelist.in > index 54d2f42..590285d 100644 > --- a/appliance/kmod.whitelist.in > +++ b/appliance/kmod.whitelist.in > @@ -26,6 +26,7 @@ ext4*.ko > crc16.ko > jbd.ko > jbd2.ko > +mbcache.ko > > fuse.ko > > -- > 1.6.3.3 > ACK. > >From 5f5c75e91508f25dee8da7b5909c446b43ce3167 Mon Sep 17 00:00:00 2001 > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Thu, 2 Jul 2009 10:46:37 +0200 > Subject: [PATCH 2/4] unconditionally load dm module > > needed for device mapper (LVM) > --- > appliance/init | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/appliance/init b/appliance/init > index b573c46..48c7c34 100755 > --- a/appliance/init > +++ b/appliance/init > @@ -31,9 +31,9 @@ else > > modprobe virtio_pci > modprobe virtio_net > - modprobe dm_mod ||: > fi > > +modprobe dm_mod ||: > mount > ls -l /dev > > -- > 1.6.3.3 > ACK. > >From 6a0300f68d57a55e998db6a47874e50c2ac5f3f0 Mon Sep 17 00:00:00 2001 > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Tue, 16 Jun 2009 23:47:36 +0200 > Subject: [PATCH 3/4] add debirf files > > --- > appliance/debian/debirf.conf.in | 5 ++ > appliance/debian/modules/a0_motd | 1 + > appliance/debian/modules/a0_prep-root | 1 + > appliance/debian/modules/install_kernel | 68 ++++++++++++++++++++++++++ > appliance/debian/modules/network | 1 + > appliance/debian/modules/root-bashrc | 1 + > appliance/debian/modules/serial-terminal | 1 + > appliance/debian/modules/y0_install-guestfsd | 33 ++++++++++++ > appliance/debian/modules/z0_remove-aptitude | 1 + > appliance/debian/modules/z0_remove-locales | 1 + > appliance/debian/modules/z1_clean-root | 1 + > appliance/debian/modules/z99_final-cleanups | 3 + > configure.ac | 1 + > 13 files changed, 118 insertions(+), 0 deletions(-) > create mode 100644 appliance/debian/debirf.conf.in > create mode 120000 appliance/debian/modules/a0_motd > create mode 120000 appliance/debian/modules/a0_prep-root > create mode 100755 appliance/debian/modules/install_kernel > create mode 120000 appliance/debian/modules/network > create mode 120000 appliance/debian/modules/root-bashrc > create mode 120000 appliance/debian/modules/serial-terminal > create mode 100755 appliance/debian/modules/y0_install-guestfsd > create mode 120000 appliance/debian/modules/z0_remove-aptitude > create mode 120000 appliance/debian/modules/z0_remove-locales > create mode 120000 appliance/debian/modules/z1_clean-root > create mode 100755 appliance/debian/modules/z99_final-cleanups > > diff --git a/appliance/debian/debirf.conf.in b/appliance/debian/debirf.conf.in > new file mode 100644 > index 0000000..a3dc16f > --- /dev/null > +++ b/appliance/debian/debirf.conf.in > @@ -0,0 +1,5 @@ > +DEBIRF_LABEL="debirf-libguestfs" > +DEBIRF_SUITE=@REPO@ > +DEBIRF_MIRROR=@MIRROR@/${DEBIRF_DISTRO} > +DEBIRF_KERNEL_ARCH=486 > + > diff --git a/appliance/debian/modules/a0_motd b/appliance/debian/modules/a0_motd > new file mode 120000 > index 0000000..8e3ad2f > --- /dev/null > +++ b/appliance/debian/modules/a0_motd > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/a0_motd > \ No newline at end of file > diff --git a/appliance/debian/modules/a0_prep-root b/appliance/debian/modules/a0_prep-root > new file mode 120000 > index 0000000..654bc70 > --- /dev/null > +++ b/appliance/debian/modules/a0_prep-root > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/a0_prep-root > \ No newline at end of file > diff --git a/appliance/debian/modules/install_kernel b/appliance/debian/modules/install_kernel > new file mode 100755 > index 0000000..c1076ce > --- /dev/null > +++ b/appliance/debian/modules/install_kernel > @@ -0,0 +1,68 @@ > +#!/bin/bash -e > + > +# debirf module: install-kernel > +# install a kernel package, indicated by the expected environment > +# variables: > +# DEBIRF_PATH > +# DEBIRF_ROOT > +# DEBIRF_KERNEL_PACKAGE > +# > +# *** REQUIRED MODULE *** > +# WARNING: this module is necessary for proper functioning of debirf. > +# > +# The debirf scripts were written by > +# Jameson Rollins > +# and > +# Daniel Kahn Gillmor . > +# > +# They are Copyright 2007, and are all released under the GPL, > +# version 3 or later. > + > +# clear out old modules if they exist, to avoid confusion > +rm -rf "$DEBIRF_ROOT/lib/modules" > + > +# download/copy in kernel package > +if [ -z "$DEBIRF_KERNEL_PACKAGE" ] ; then > + # determine kernel to install. assume arch of build host. > + > + # determine kernel arch. need everything after the kernel version > + # and debian version > + if [ -z "$DEBIRF_KERNEL_ARCH" ]; then > + KARCH=$(uname -r | cut -d- -f3-) > + else > + KARCH="$DEBIRF_KERNEL_ARCH" > + fi > + > + # determine the full kernel version from the dependency of the > + # generic 2.6-ARCH package in the debirf root (since it may be > + # different than what is installed on the build host) > + KNAME=$(debirf_exec apt-cache show linux-image-2.6-"$KARCH" | grep '^Depends: ' | sed 's/^Depends: //') > + > + # download only the desired kernel package directly into the apt > + # cache for dpkg extraction > + debirf_exec sh -c "cd /var/cache/apt/archives/ && aptitude download \"$KNAME\"" > +else > + # install kernel deb if given at command line > + debirf_exec sh -c "cd /var/cache/apt/archives/ && aptitude download \"$DEBIRF_KERNEL_PACKAGE\"" > +fi > + > +KPKG=$(basename "$DEBIRF_ROOT"/var/cache/apt/archives/linux-image-2.6.*) > + > +echo "extracting kernel package $KPKG..." > +debirf_exec dpkg --extract /var/cache/apt/archives/"$KPKG" / > + > +# install the module init tools, since they are needed for depmod > +debirf_exec apt-get --assume-yes install module-init-tools > + > +# depmod to create module list > +KVERS=$(ls -1 -t "$DEBIRF_ROOT/lib/modules" | head -n1) > +echo "generating modules.dep..." > +debirf_exec depmod -a "$KVERS" > + > +# extract kernel and debian stock initrd from the build root: > +mv "$DEBIRF_ROOT"/boot/vmlinu* "$DEBIRF_BUILDD" > + > +# remove kernel symlinks > +if [ -L "$DEBIRF_ROOT"/vmlinuz ] ; then > + rm "$DEBIRF_BUILDD"/vmlinuz > +fi > diff --git a/appliance/debian/modules/network b/appliance/debian/modules/network > new file mode 120000 > index 0000000..979418d > --- /dev/null > +++ b/appliance/debian/modules/network > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/network > \ No newline at end of file > diff --git a/appliance/debian/modules/root-bashrc b/appliance/debian/modules/root-bashrc > new file mode 120000 > index 0000000..651d030 > --- /dev/null > +++ b/appliance/debian/modules/root-bashrc > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/root-bashrc > \ No newline at end of file > diff --git a/appliance/debian/modules/serial-terminal b/appliance/debian/modules/serial-terminal > new file mode 120000 > index 0000000..a5376da > --- /dev/null > +++ b/appliance/debian/modules/serial-terminal > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/serial-terminal > \ No newline at end of file > diff --git a/appliance/debian/modules/y0_install-guestfsd b/appliance/debian/modules/y0_install-guestfsd > new file mode 100755 > index 0000000..17bbbdc > --- /dev/null > +++ b/appliance/debian/modules/y0_install-guestfsd > @@ -0,0 +1,33 @@ > +#!/bin/bash -e > +# install guestfsd specific stuff > + > +# Kernel modules take up nearly half of the image. Only include ones > +# which are on the whitelist. > +exec 5<../appliance/kmod.whitelist > +whitelist= > +while read kmod 0<&5; do > + whitelist="$whitelist -a -not -name $kmod" > +done > +exec 5<&- > + > +echo "Module whitelist: $whitelist" > +find $DEBIRF_ROOT/lib/modules/*/kernel -name '*.ko' $whitelist -a -exec rm '{}' \; > + > +# install additional packages: > +PKGLIST=$(< packagelist) > +echo "Will add $PKGLIST" > +debirf_exec aptitude -R -y install $PKGLIST > +debirf_exec aptitude -y remove vim-tiny dhcp3-client iptables > + > +debirf_exec mkdir -p --mode=0777 /sysroot > + > +# cleanup some other heavy lifters: > +rm -rf "$DEBIRF_ROOT"/usr/share/doc/ > +rm -rf "$DEBIRF_ROOT"/usr/share/zoneinfo/ > +rm -rf "$DEBIRF_ROOT"/usr/share/man/ > + > +# Install the actual appliance: > +echo $PWD > +install -o root -g root -m 0755 ../daemon/guestfsd "$DEBIRF_ROOT"/sbin/guestfsd > +install -o root -g root -m 0755 init "$DEBIRF_ROOT"/sbin/init > + > diff --git a/appliance/debian/modules/z0_remove-aptitude b/appliance/debian/modules/z0_remove-aptitude > new file mode 120000 > index 0000000..7c56260 > --- /dev/null > +++ b/appliance/debian/modules/z0_remove-aptitude > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/z0_remove-aptitude > \ No newline at end of file > diff --git a/appliance/debian/modules/z0_remove-locales b/appliance/debian/modules/z0_remove-locales > new file mode 120000 > index 0000000..80a82fa > --- /dev/null > +++ b/appliance/debian/modules/z0_remove-locales > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/z0_remove-locales > \ No newline at end of file > diff --git a/appliance/debian/modules/z1_clean-root b/appliance/debian/modules/z1_clean-root > new file mode 120000 > index 0000000..f0d3aad > --- /dev/null > +++ b/appliance/debian/modules/z1_clean-root > @@ -0,0 +1 @@ > +/usr/share/debirf/modules/z1_clean-root > \ No newline at end of file > diff --git a/appliance/debian/modules/z99_final-cleanups b/appliance/debian/modules/z99_final-cleanups > new file mode 100755 > index 0000000..ef5fac7 > --- /dev/null > +++ b/appliance/debian/modules/z99_final-cleanups > @@ -0,0 +1,3 @@ > +#!/bin/sh > + > +rm -rf "$DEBIRF_ROOT"/var/lib/dpkg/info > diff --git a/configure.ac b/configure.ac > index 1625327..03f9388 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -523,6 +523,7 @@ AC_CONFIG_FILES([appliance/libguestfs-supermin-helper], > AC_CONFIG_FILES([Makefile > src/Makefile fish/Makefile po/Makefile.in examples/Makefile > appliance/Makefile > + appliance/debian/debirf.conf > images/Makefile > capitests/Makefile > regressions/Makefile > -- > 1.6.3.3 > Yes, this looks fine now. +1 > >From ef4d9afa2d958dec3c52b4d627b87245c9ba754b Mon Sep 17 00:00:00 2001 > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Tue, 30 Jun 2009 15:01:14 +0200 > Subject: [PATCH 4/4] Build Debian based appliance using debirf > > --- > appliance/make.sh.in | 236 +++++++++++++++++++++++++----------------------- > appliance/update.sh.in | 26 ++++-- > 2 files changed, 139 insertions(+), 123 deletions(-) > > diff --git a/appliance/make.sh.in b/appliance/make.sh.in > index 637bd07..e98c325 100755 > --- a/appliance/make.sh.in > +++ b/appliance/make.sh.in > @@ -22,125 +22,131 @@ unset CDPATH > > set -e > > -cd @top_builddir@ > - > -# Decide on names for the final output. These have to match Makefile.am. > -output=appliance/initramfs. at REPO@. at host_cpu@.img > -koutput=appliance/vmlinuz. at REPO@. at host_cpu@ > -rm -f $output > -rm -f $koutput > - > -# Create the basic initramfs. > -exec 5 -packages= > -while read pkg 0<&5; do > - packages="$packages -i $pkg" > -done > -exec 5<&- > - > - at FEBOOTSTRAP@ $packages -u @UPDATES@ @REPO@ initramfs @MIRROR@ > - > -# /sysroot is where the guest root filesystem will be mounted. > - at FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /sysroot > - > -# Create /tmp if it is missing. > - at FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /tmp > - > -# Nuke some stuff. The kernel pulls mkinitrd and plymouth which pulls in > -# all of Python. Sheez. > -(cd initramfs && find -name '*plymouth*' -print0) | > - xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > -(cd initramfs && find -name '*python*' -print0) | > - xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > - > -# In Fedora >= 11, it pulls in all of Perl from somewhere. Nuke from orbit. > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/perl5 /usr/lib64/perl5 > - > -# Anaconda? JPEG images? > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/anaconda-runtime > - > -# Don't need any firmware. > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/firmware > - > -# Don't need any keyboard maps. > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/kbd > - > -# Remove anything in home directory. Because this is potentially > -# liable to monstrous fuck-ups, we don't put a slash before 'home'. > -(cd initramfs && echo home/*) | > - xargs @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > - > -# Remove /var/lib/yum stuff. > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf /var/lib/yum > - > -# Remove some unreadable binaries which are incompatible with > -# the supermin appliance. Since these binaries can't be read > -# from the host filesystem, they generate warnings like: > -# cpio: ./usr/bin/chfn: Cannot open: Permission denied > -# These binaries are not needed for operation of the appliance. > - at FEBOOTSTRAP_RUN@ initramfs -- rm -f \ > - /usr/bin/chfn \ > - /usr/bin/chsh \ > - /usr/libexec/pt_chown \ > - /usr/sbin/groupdel \ > - /usr/sbin/groupadd \ > - /usr/sbin/useradd \ > - /usr/sbin/tzdata-update \ > - /usr/sbin/userdel \ > - /usr/sbin/usermod \ > - /usr/sbin/groupmod \ > - /usr/sbin/groupmems \ > - /sbin/unix_update \ > - $(cd initramfs && echo usr/sbin/glibc_post_upgrade.*) > - > -# Kernel modules take up nearly half of the image. Only include ones > -# which are on the whitelist. > -exec 5 -whitelist= > -while read kmod 0<&5; do > - whitelist="$whitelist -a -not -name $kmod" > -done > -exec 5<&- > - > -(cd initramfs && \ > - find lib/modules/*/kernel -name '*.ko' $whitelist -a -print0 ) | > - xargs -0 febootstrap-run initramfs -- rm > - > -# Pull the kernel out into the current directory. We don't want it in > -# the initramfs image. > -cp initramfs/boot/vmlinuz* $koutput > - at FEBOOTSTRAP_RUN@ initramfs -- rm -rf boot > - > -# Minimize the image. > - at FEBOOTSTRAP_MINIMIZE@ initramfs > - > -# Add some missing configuration files. > -if [ ! -f initramfs/etc/hosts ]; then > - cat > hosts.new <<'__EOF__' > -127.0.0.1 guestfs localhost.localdomain localhost > -::1 localhost6.localdomain6 localhost6 > +if [ "@DIST@" = "REDHAT" ]; then > + cd @top_builddir@ > + # Decide on names for the final output. These have to match Makefile.am. > + output=appliance/initramfs. at REPO@. at host_cpu@.img > + koutput=appliance/vmlinuz. at REPO@. at host_cpu@ > + rm -f $output > + rm -f $koutput > + > + # Create the basic initramfs. > + exec 5 + packages= > + while read pkg 0<&5; do > + packages="$packages -i $pkg" > + done > + exec 5<&- > + > + @FEBOOTSTRAP@ $packages -u @UPDATES@ @REPO@ initramfs @MIRROR@ > + > + # /sysroot is where the guest root filesystem will be mounted. > + @FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /sysroot > + > + # Create /tmp if it is missing. > + @FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /tmp > + > + # Nuke some stuff. The kernel pulls mkinitrd and plymouth which pulls in > + # all of Python. Sheez. > + (cd initramfs && find -name '*plymouth*' -print0) | > + xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > + (cd initramfs && find -name '*python*' -print0) | > + xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > + > + # In Fedora >= 11, it pulls in all of Perl from somewhere. Nuke from orbit. > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/perl5 /usr/lib64/perl5 > + > + # Anaconda? JPEG images? > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/anaconda-runtime > + > + # Don't need any firmware. > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/firmware > + > + # Don't need any keyboard maps. > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/kbd > + > + # Remove anything in home directory. Because this is potentially > + # liable to monstrous fuck-ups, we don't put a slash before 'home'. > + (cd initramfs && echo home/*) | > + xargs @FEBOOTSTRAP_RUN@ initramfs -- rm -rf > + > + # Remove /var/lib/yum stuff. > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf /var/lib/yum > + > + # Remove some unreadable binaries which are incompatible with > + # the supermin appliance. Since these binaries can't be read > + # from the host filesystem, they generate warnings like: > + # cpio: ./usr/bin/chfn: Cannot open: Permission denied > + # These binaries are not needed for operation of the appliance. > + @FEBOOTSTRAP_RUN@ initramfs -- rm -f \ > + /usr/bin/chfn \ > + /usr/bin/chsh \ > + /usr/libexec/pt_chown \ > + /usr/sbin/groupdel \ > + /usr/sbin/groupadd \ > + /usr/sbin/useradd \ > + /usr/sbin/tzdata-update \ > + /usr/sbin/userdel \ > + /usr/sbin/usermod \ > + /usr/sbin/groupmod \ > + /usr/sbin/groupmems \ > + /sbin/unix_update \ > + $(cd initramfs && echo usr/sbin/glibc_post_upgrade.*) > + > + # Kernel modules take up nearly half of the image. Only include ones > + # which are on the whitelist. > + exec 5 + whitelist= > + while read kmod 0<&5; do > + whitelist="$whitelist -a -not -name $kmod" > + done > + exec 5<&- > + > + (cd initramfs && \ > + find lib/modules/*/kernel -name '*.ko' $whitelist -a -print0 ) | > + xargs -0 febootstrap-run initramfs -- rm > + > + # Pull the kernel out into the current directory. We don't want it in > + # the initramfs image. > + cp initramfs/boot/vmlinuz* $koutput > + @FEBOOTSTRAP_RUN@ initramfs -- rm -rf boot > + > + # Minimize the image. > + @FEBOOTSTRAP_MINIMIZE@ initramfs > + > + # Add some missing configuration files. > + if [ ! -f initramfs/etc/hosts ]; then > + cat > hosts.new <<'__EOF__' > + 127.0.0.1 guestfs localhost.localdomain localhost > + ::1 localhost6.localdomain6 localhost6 > __EOF__ > - @FEBOOTSTRAP_INSTALL@ initramfs hosts.new /etc/hosts 0644 root.root > - rm hosts.new > -fi > + @FEBOOTSTRAP_INSTALL@ initramfs hosts.new /etc/hosts 0644 root.root > + rm hosts.new > + fi > > -if [ ! -f initramfs/etc/fstab ]; then > - @FEBOOTSTRAP_RUN@ initramfs -- touch /etc/fstab > -fi > + if [ ! -f initramfs/etc/fstab ]; then > + @FEBOOTSTRAP_RUN@ initramfs -- touch /etc/fstab > + fi > + > + echo nameserver 10.0.2.3 > resolv.conf.new > + @FEBOOTSTRAP_INSTALL@ initramfs resolv.conf.new /etc/resolv.conf 0644 root.root > + rm resolv.conf.new > > -echo nameserver 10.0.2.3 > resolv.conf.new > - at FEBOOTSTRAP_INSTALL@ initramfs resolv.conf.new /etc/resolv.conf 0644 root.root > -rm resolv.conf.new > + # Create the init script. > + @FEBOOTSTRAP_INSTALL@ initramfs appliance/init /init 0755 root.root > > -# Create the init script. > - at FEBOOTSTRAP_INSTALL@ initramfs appliance/init /init 0755 root.root > + # Just in case the kernel isn't looking for /init, make /sbin/init > + # be our script, not the real init. > + #@FEBOOTSTRAP_RUN@ initramfs -- ln -f /init /sbin/init > > -# Just in case the kernel isn't looking for /init, make /sbin/init > -# be our script, not the real init. > -#@FEBOOTSTRAP_RUN@ initramfs -- ln -f /init /sbin/init > + ls -lh $koutput > > -ls -lh $koutput > + # Now directly run the update script to copy/update the daemon in the > + # initramfs. > + cd appliance && bash update.sh > + > +elif [ "@DIST@" = "DEBIAN" ]; then > + cd @top_builddir@/appliance > + debirf make -n debian > +fi > > -# Now directly run the update script to copy/update the daemon in the > -# initramfs. > -cd appliance && bash update.sh > diff --git a/appliance/update.sh.in b/appliance/update.sh.in > index 3b779f8..4fbd651 100755 > --- a/appliance/update.sh.in > +++ b/appliance/update.sh.in > @@ -23,14 +23,24 @@ unset CDPATH > > set -e > > -cd @top_builddir@ > +if [ "@DIST@" = "REDHAT" ]; then > + cd @top_builddir@ > + output=appliance/initramfs. at REPO@. at host_cpu@.img > > -output=appliance/initramfs. at REPO@. at host_cpu@.img > + # Copy the daemon into the filesystem. > + @FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root > > -# Copy the daemon into the filesystem. > - at FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root > + # Generate final image. > + @FEBOOTSTRAP_TO_INITRAMFS@ initramfs > $output-t > + mv $output-t $output > + ls -lh $output > +elif [ "@DIST@" = "DEBIAN" ]; then > + cd @top_builddir@/appliance > + > + output=initramfs. at REPO@. at host_cpu@.img > + vmlinuz=vmlinuz. at REPO@. at host_cpu@ > + > + ln -sf debian/debirf-libguestfs_ at REPO@*.cgz $output > + ln -sf debian/vmlinuz-* $vmlinuz > +fi > > -# Generate final image. > - at FEBOOTSTRAP_TO_INITRAMFS@ initramfs > $output-t > -mv $output-t $output > -ls -lh $output > -- > 1.6.3.3 > Yes, also fine. I'll apply these patches to libguestfs git repo shortly. Thanks for your contribution! Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Thu Jul 2 12:17:32 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 13:17:32 +0100 Subject: [fedora-virt] [PATCH] arrange to build some generated sources In-Reply-To: <874otvuxqm.fsf@meyering.net> References: <874otvuxqm.fsf@meyering.net> Message-ID: <20090702121732.GA23290@amd.home.annexia.org> On Thu, Jul 02, 2009 at 01:32:01PM +0200, Jim Meyering wrote: > Hi Rich, > > I've just pulled the latest, and then ran this: > > git clean -x -d -f && ./autogen.sh > > First problem was this: > > *** No rule to make target `guestfs-structs.h' > > I worked around it with the patch below, That patch is fine, +1. > but then got this: > > libtool: link: CURRENT `' must be a nonnegative integer > libtool: link: `:0:' is not valid version information > make[3]: *** [libguestfs.la] Error 1 This should be fixed by this commit: http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=cf61715fa7f8dcf644bebebfa7f2741d8d79a644 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From jim at meyering.net Thu Jul 2 12:20:01 2009 From: jim at meyering.net (Jim Meyering) Date: Thu, 02 Jul 2009 14:20:01 +0200 Subject: [fedora-virt] [PATCH libguestfs] avoid automake failure Message-ID: <87tz1vtgy6.fsf@meyering.net> Running autoreconf -i in libguestfs, I get this: Makefile.am:21: compiling `augeas.c' with per-target flags requires `AM_PROG_CC_C_O' in `configure.ac' Here's the patch: >From 9ce260c5aff7bc916b368d1dbc533a7f659db320 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 2 Jul 2009 13:36:04 +0200 Subject: [PATCH] avoid automake failure * daemon/configure.ac: Use AM_PROG_CC_C_O, not AC_PROG_CC_C_O. --- daemon/configure.ac | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/daemon/configure.ac b/daemon/configure.ac index a91db6d..6ecbb8a 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -44,7 +44,7 @@ AC_PROG_CPP AC_C_PROTOTYPES test "x$U" != "x" && AC_MSG_ERROR([Compiler not ANSI compliant]) -AC_PROG_CC_C_O +AM_PROG_CC_C_O dnl Check for Augeas (now optional). AC_CHECK_LIB([augeas],[aug_match],[ -- 1.6.3.3.507.gc6b5a From rjones at redhat.com Thu Jul 2 12:22:24 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 13:22:24 +0100 Subject: [fedora-virt] [PATCH libguestfs] avoid automake failure In-Reply-To: <87tz1vtgy6.fsf@meyering.net> References: <87tz1vtgy6.fsf@meyering.net> Message-ID: <20090702122224.GA23354@amd.home.annexia.org> On Thu, Jul 02, 2009 at 02:20:01PM +0200, Jim Meyering wrote: > Running autoreconf -i in libguestfs, I get this: > > Makefile.am:21: compiling `augeas.c' with per-target flags requires `AM_PROG_CC_C_O' in `configure.ac' > > Here's the patch: ACK, obvious fix. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Thu Jul 2 13:38:33 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 14:38:33 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <4A4B9B82.1010506@redhat.com> References: <4A4B9B82.1010506@redhat.com> Message-ID: <20090702133833.GA23913@amd.home.annexia.org> On Wed, Jul 01, 2009 at 06:23:14PM +0100, Matthew Booth wrote: > This is only subjective, and could yet be something entirely random on > my machine. However, I just pulled changes > 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe > and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 times > slower. Is it just me? It turns out that two commands take a lot longer to run with a virtio backend than with an IDE backend. They are: mkfs.ext2 zerofree At the moment I have no idea why this is. I'm about to push some very simple command-level profiling into the daemon. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From berrange at redhat.com Thu Jul 2 13:51:41 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 2 Jul 2009 14:51:41 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <20090702133833.GA23913@amd.home.annexia.org> References: <4A4B9B82.1010506@redhat.com> <20090702133833.GA23913@amd.home.annexia.org> Message-ID: <20090702135141.GC16617@redhat.com> On Thu, Jul 02, 2009 at 02:38:33PM +0100, Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 06:23:14PM +0100, Matthew Booth wrote: > > This is only subjective, and could yet be something entirely random on > > my machine. However, I just pulled changes > > 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe > > and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 times > > slower. Is it just me? > > It turns out that two commands take a lot longer to run > with a virtio backend than with an IDE backend. They are: > > mkfs.ext2 > zerofree > > At the moment I have no idea why this is. We've had that reported with F11 + virtio + sparse files, but unable to reliably reproduce it thus far, so no resolution on the bug... https://bugzilla.redhat.com/show_bug.cgi?id=504376 "F-11 guest takes 45 minutes in mke2fs for 8gb fs on virtio disk with a sparse backing file" Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From rjones at redhat.com Thu Jul 2 14:17:10 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 15:17:10 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <20090702133833.GA23913@amd.home.annexia.org> References: <4A4B9B82.1010506@redhat.com> <20090702133833.GA23913@amd.home.annexia.org> Message-ID: <20090702141710.GB23913@amd.home.annexia.org> On Thu, Jul 02, 2009 at 02:38:33PM +0100, Richard W.M. Jones wrote: > On Wed, Jul 01, 2009 at 06:23:14PM +0100, Matthew Booth wrote: > > This is only subjective, and could yet be something entirely random on > > my machine. However, I just pulled changes > > 3d15f7e652340777514ff30c3cfc560a90b612ec..99e28249d52ca5495b636e14ae3e4387ee62c8fe > > and now 'make check' runs a *lot* slower. I'm guessing maybe 5-10 times > > slower. Is it just me? > > It turns out that two commands take a lot longer to run > with a virtio backend than with an IDE backend. They are: > > mkfs.ext2 > zerofree > > At the moment I have no idea why this is. > > I'm about to push some very simple command-level profiling > into the daemon. Dan pointed me to this bug which looks relevant: https://bugzilla.redhat.com/show_bug.cgi?id=504376 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Thu Jul 2 14:27:32 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 15:27:32 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <20090702141710.GB23913@amd.home.annexia.org> References: <4A4B9B82.1010506@redhat.com> <20090702133833.GA23913@amd.home.annexia.org> <20090702141710.GB23913@amd.home.annexia.org> Message-ID: <20090702142732.GC23913@amd.home.annexia.org> On Thu, Jul 02, 2009 at 03:17:10PM +0100, Richard W.M. Jones wrote: > Dan pointed me to this bug which looks relevant: > > https://bugzilla.redhat.com/show_bug.cgi?id=504376 However it's not sparseness which is the problem. Even with non-sparse backing files (see attached patch) I still see a slowdown. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ -------------- next part -------------- diff --git a/src/generator.ml b/src/generator.ml index f41413e..3387136 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -4405,7 +4405,6 @@ static void no_test_warnings (void) pr "\ int main (int argc, char *argv[]) { - char c = 0; int failed = 0; const char *filename; int fd; @@ -4431,14 +4430,8 @@ int main (int argc, char *argv[]) perror (filename); exit (1); } - if (lseek (fd, %d, SEEK_SET) == -1) { - perror (\"lseek\"); - close (fd); - unlink (filename); - exit (1); - } - if (write (fd, &c, 1) == -1) { - perror (\"write\"); + if (posix_fallocate (fd, 0, %d) == -1) { + perror (\"fallocate\"); close (fd); unlink (filename); exit (1); @@ -4459,14 +4452,8 @@ int main (int argc, char *argv[]) perror (filename); exit (1); } - if (lseek (fd, %d, SEEK_SET) == -1) { - perror (\"lseek\"); - close (fd); - unlink (filename); - exit (1); - } - if (write (fd, &c, 1) == -1) { - perror (\"write\"); + if (posix_fallocate (fd, 0, %d) == -1) { + perror (\"fallocate\"); close (fd); unlink (filename); exit (1); @@ -4487,14 +4474,8 @@ int main (int argc, char *argv[]) perror (filename); exit (1); } - if (lseek (fd, %d, SEEK_SET) == -1) { - perror (\"lseek\"); - close (fd); - unlink (filename); - exit (1); - } - if (write (fd, &c, 1) == -1) { - perror (\"write\"); + if (posix_fallocate (fd, 0, %d) == -1) { + perror (\"fallocate\"); close (fd); unlink (filename); exit (1); From loganjerry at gmail.com Thu Jul 2 14:40:58 2009 From: loganjerry at gmail.com (Jerry James) Date: Thu, 2 Jul 2009 08:40:58 -0600 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <20090701083751.GA10894@amd.home.annexia.org> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> Message-ID: <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> On Wed, Jul 1, 2009 at 2:37 AM, Richard W.M. Jones wrote: > libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen > different virtualization systems, giving you the benefit of > abstracting the details of the hypervisor from the management tools. > So for that reason we don't support tweaking the qemu command line > arbitrarily. ?However if there are particular features of qemu or KVM > that you think we should support, please raise them. 1) Higher resolution. My boss gave me two big monitors that can do 1920x1200, and all I can get for my guest machines is tiny little windows with hardly any room to work inside. 2) The ability to see what options qemu-kvm was invoked with. Even if I can't change them, at least I can understand what I am getting. Right now, it's a black box to me. Incidentally, the guest machine that I described in the first message in this thread is using the virt-blk driver, so I wonder if I'm seeing the same problem as described in the thread on the test slowdowns. I just checked, and the disk image is sparse, although there seems to be some doubt that that has anything to do with the problem. -- Jerry James http://www.jamezone.org/ From rjones at redhat.com Thu Jul 2 14:47:37 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 15:47:37 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <20090702142732.GC23913@amd.home.annexia.org> References: <4A4B9B82.1010506@redhat.com> <20090702133833.GA23913@amd.home.annexia.org> <20090702141710.GB23913@amd.home.annexia.org> <20090702142732.GC23913@amd.home.annexia.org> Message-ID: <20090702144737.GD23913@amd.home.annexia.org> https://bugzilla.redhat.com/show_bug.cgi?id=509383 New bug created for this issue. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From rjones at redhat.com Thu Jul 2 15:07:09 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 16:07:09 +0100 Subject: [fedora-virt] libguestfs tests running much slower In-Reply-To: <20090702135141.GC16617@redhat.com> References: <4A4B9B82.1010506@redhat.com> <20090702133833.GA23913@amd.home.annexia.org> <20090702135141.GC16617@redhat.com> Message-ID: <20090702150709.GD22036@amd.home.annexia.org> On Thu, Jul 02, 2009 at 02:51:41PM +0100, Daniel P. Berrange wrote: > We've had that reported with F11 + virtio + sparse files, but unable to > reliably reproduce it thus far, so no resolution on the bug... > > https://bugzilla.redhat.com/show_bug.cgi?id=504376 > > "F-11 guest takes 45 minutes in mke2fs for 8gb fs on virtio disk with a sparse backing file" I opened another bug because we see the same issue WITHOUT a sparse backing disk. We've also got it nailed with an easy reproducer script. https://bugzilla.redhat.com/show_bug.cgi?id=509383 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Thu Jul 2 15:10:50 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 16:10:50 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> Message-ID: <20090702151050.GE22036@amd.home.annexia.org> On Thu, Jul 02, 2009 at 08:40:58AM -0600, Jerry James wrote: > On Wed, Jul 1, 2009 at 2:37 AM, Richard W.M. Jones wrote: > > libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen > > different virtualization systems, giving you the benefit of > > abstracting the details of the hypervisor from the management tools. > > So for that reason we don't support tweaking the qemu command line > > arbitrarily. ?However if there are particular features of qemu or KVM > > that you think we should support, please raise them. > > 1) Higher resolution. My boss gave me two big monitors that can do > 1920x1200, and all I can get for my guest machines is tiny little > windows with hardly any room to work inside. This is a limitation of the emulated Cirrus Logic graphics card. In the days or yore when those real graphics chipsets existed [I even had one] 800x600 and 1024x768 in 16 bits was regarded as the cutting edge. Eventually we'll have open source SPICE support (PV graphics driver) which massively improves resolution and performance. For example, SPICE can stream videos by recompressing them on the fly between the guest and host. > 2) The ability to see what options qemu-kvm was invoked with. Even if > I can't change them, at least I can understand what I am getting. > Right now, it's a black box to me. I believe this is being worked on in upstream libvirt. Also the other way around (turn a qemu command line into a libvirt configuration file). Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From loganjerry at gmail.com Thu Jul 2 15:18:34 2009 From: loganjerry at gmail.com (Jerry James) Date: Thu, 2 Jul 2009 09:18:34 -0600 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <20090702151050.GE22036@amd.home.annexia.org> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> <20090702151050.GE22036@amd.home.annexia.org> Message-ID: <870180fe0907020818h349adb4fr9f4d092604af4e47@mail.gmail.com> On Thu, Jul 2, 2009 at 9:10 AM, Richard W.M. Jones wrote: > This is a limitation of the emulated Cirrus Logic graphics card. ?In > the days or yore when those real graphics chipsets existed [I even had > one] 800x600 and 1024x768 in 16 bits was regarded as the cutting edge. Sure, but I can get a window NOW with a resolution I consider reasonable by running qemu-kvm -vga std. Even with the other benefits of virt-manager, I'm tempted to drop it just for the bigger window. I'm actually writing code inside the VMs (long story) and I need room. I well remember CGA graphics. EGA was great, VGA was greater, and SVGA was just amazing! Except, today, I am used to side-by-side monitors that do 1920x1200. Spoiled? Perhaps. > Eventually we'll have open source SPICE support (PV graphics driver) > which massively improves resolution and performance. ?For example, > SPICE can stream videos by recompressing them on the fly between the > guest and host. I don't care about video. I just want room for my accustomed programming tools. I'm starting to whine. I hate whiners. Thanks for all the work on making virtualization in Fedora better. It really is appreciated, in spite of the whining. :-) -- Jerry James http://www.jamezone.org/ From rich at lat.com Thu Jul 2 15:24:26 2009 From: rich at lat.com (Rich Mahn) Date: Thu, 02 Jul 2009 11:24:26 -0400 Subject: [fedora-virt] another nfs problem with virt-manager Message-ID: <200907021524.n62FOQ6E004924@raspberry.lat.com> Trying to create a new virtual machine using virt-manager. Select Network install (HTTP,FTP, or NFS) Enter the URL as nfs://machine/mount_loc Nothing in Kickstart URL or Kernel Options Check Automatically detect operating system selet forward and get this error pop-up "Error setting install media location. Privilege is required for NFS installations" When I started virt-manager from a normal account, it asked and received the root password. This was my attempt to get around the prohibition against using nfs files (unfixed bug for the moment), but this try didn't work either. Any ideas? thanks for everyone's help From tom.horsley at att.net Thu Jul 2 15:43:43 2009 From: tom.horsley at att.net (Tom Horsley) Date: Thu, 2 Jul 2009 11:43:43 -0400 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0907020818h349adb4fr9f4d092604af4e47@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> <20090702151050.GE22036@amd.home.annexia.org> <870180fe0907020818h349adb4fr9f4d092604af4e47@mail.gmail.com> Message-ID: <20090702114343.5cb5ad9e@zooty> On Thu, 2 Jul 2009 09:18:34 -0600 Jerry James wrote: > I don't care about video. I just want room for my accustomed programming tools. Do what I do - don't use the console at all, run a vncserver in the virtual machine and connect to it from the outside with vncviewer - get any resolution you want :-). From loganjerry at gmail.com Thu Jul 2 15:49:24 2009 From: loganjerry at gmail.com (Jerry James) Date: Thu, 2 Jul 2009 09:49:24 -0600 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <20090702114343.5cb5ad9e@zooty> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> <20090702151050.GE22036@amd.home.annexia.org> <870180fe0907020818h349adb4fr9f4d092604af4e47@mail.gmail.com> <20090702114343.5cb5ad9e@zooty> Message-ID: <870180fe0907020849w79d34497ka5d930998f7107e2@mail.gmail.com> On Thu, Jul 2, 2009 at 9:43 AM, Tom Horsley wrote: > Do what I do - don't use the console at all, run a vncserver in the virtual > machine and connect to it from the outside with vncviewer - get any resolution > you want :-). <*Sound of a light bulb going on in Jerry's brain*> Where were you 5 months ago when I was getting started with virtual machines? :-) Thanks a ton. -- Jerry James http://www.jamezone.org/ From loganjerry at gmail.com Thu Jul 2 14:55:47 2009 From: loganjerry at gmail.com (Jerry James) Date: Thu, 2 Jul 2009 08:55:47 -0600 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> Message-ID: <870180fe0907020755s142137c6o7c10f1ce5881c94f@mail.gmail.com> On Thu, Jul 2, 2009 at 8:40 AM, Jerry James wrote: > Incidentally, the guest machine that I described in the first message > in this thread is using the virt-blk driver, so I wonder if I'm seeing > the same problem as described in the thread on the test slowdowns. ?I > just checked, and the disk image is sparse, although there seems to be > some doubt that that has anything to do with the problem. I just made a Rawhide virtual machine to see if it suffers from the same problem. Zillions of copies of this message are being spewed to the console, although the machine itself seems to be running normally (if sluggishly): end_request: I/O error, dev vda, sector 0 Any idea what that's all about? -- Jerry James http://www.jamezone.org/ From berrange at redhat.com Thu Jul 2 17:19:45 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Thu, 2 Jul 2009 18:19:45 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <4A49B125.8080509@redhat.com> <870180fe0906301309l26d9deefkc9a8cb84881a87eb@mail.gmail.com> <20090701083751.GA10894@amd.home.annexia.org> <870180fe0907020740k4a6cd536o1a2a26c96c73583d@mail.gmail.com> Message-ID: <20090702171945.GA13324@redhat.com> On Thu, Jul 02, 2009 at 08:40:58AM -0600, Jerry James wrote: > On Wed, Jul 1, 2009 at 2:37 AM, Richard W.M. Jones wrote: > > libvirt isn't just a wrapper around qemu-kvm, it drives half a dozen > > different virtualization systems, giving you the benefit of > > abstracting the details of the hypervisor from the management tools. > > So for that reason we don't support tweaking the qemu command line > > arbitrarily. ?However if there are particular features of qemu or KVM > > that you think we should support, please raise them. > > 1) Higher resolution. My boss gave me two big monitors that can do > 1920x1200, and all I can get for my guest machines is tiny little > windows with hardly any room to work inside. We'll have support for alternative graphics adapters in F12 libvirt which will allow this, at least better than now > 2) The ability to see what options qemu-kvm was invoked with. Even if > I can't change them, at least I can understand what I am getting. > Right now, it's a black box to me. Any VM you launched has its args logged in /var/log/libvirt/qemu/$NAME.log Come F12 you can also explicitly do conversions without starting a VM http://libvirt.org/drvqemu.html#imex Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From rjones at redhat.com Thu Jul 2 20:58:22 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 21:58:22 +0100 Subject: [fedora-virt] Fwd: Bug#530427: Updated Debian packages [for libguestfs] Message-ID: <20090702205822.GA26887@amd.home.annexia.org> See also: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=530427 ----- Forwarded message from Guido G?nther ----- Subject: Bug#530427: Updated Debian packages Date: Thu, 2 Jul 2009 22:15:05 +0200 From: Guido G?nther Hi, I've uploaded updated libguestfs[1] Debian packges - based on the ones from Richard - to: http://pkg-libvirt.alioth.debian.org/packages/squeeze/ Changes are: * debian based appliance * python bindings * debug package * doc package * uses cdbs now We still need to add a smart way to either recreate the appliance during package installation or swith to the supermin appliance before uploading into the archive. Cheers, -- Guido [1] http://libguestfs.org ----- End forwarded message ----- -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From jim at meyering.net Thu Jul 2 21:16:37 2009 From: jim at meyering.net (Jim Meyering) Date: Thu, 02 Jul 2009 23:16:37 +0200 Subject: [fedora-virt] [PATCH libguestfs] use xmalloc and xcalloc in generated code Message-ID: <87tz1uss3u.fsf@meyering.net> Hi Rich, I noticed that there were some unchecked malloc and calloc return values. That could result in NULL deref upon failed allocation. Based on what you said about there not being much point in trying to recover from OOM errors, I made the small textual change to convert e.g., malloc(n) to xmalloc(g,n) where xmalloc now ends up calling g->abort_cb upon malloc failure. Then any following dereference of the result is guaranteed to be valid. Since I did the same with the calloc->xcalloc transformation, I needed a corresponding guestfs_safe_calloc function wrapper. >From 9f39ef2f45b4d5fe93b69d5a42fab69ba0b3e633 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 2 Jul 2009 15:39:08 +0200 Subject: [PATCH] use xmalloc and xcalloc in generated code * src/generator.ml (xmalloc): Define to guestfs_safe_malloc. (xcalloc): Define to guestfs_safe_calloc. [most generated code]: Fail immediately upon failure of otherwise- unchecked malloc and calloc calls. * src/guestfs.c: Include . (xalloc_oversized): Define. * src/guestfs.h (guestfs_safe_calloc): Declare. --- src/generator.ml | 44 +++++++++++++++++++++++--------------------- src/guestfs.c | 39 ++++++++++++++++++++++++++++++++++++++- src/guestfs.h | 3 ++- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/generator.ml b/src/generator.ml index abe7e89..da93b70 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -121,7 +121,7 @@ type flags = | NotInDocs (* do not add this function to documentation *) let protocol_limit_warning = - "Because of the message protocol, there is a transfer limit + "Because of the message protocol, there is a transfer limit of somewhere between 2MB and 4MB. To transfer large files you should use FTP." @@ -6384,7 +6384,7 @@ Sys::Guestfs - Perl bindings for libguestfs =head1 SYNOPSIS use Sys::Guestfs; - + my $h = Sys::Guestfs->new (); $h->add_drive ('guest.img'); $h->launch (); @@ -8132,6 +8132,8 @@ and generate_bindtests () = #include \"guestfs_protocol.h\" #define error guestfs_error +#define xmalloc guestfs_safe_malloc +#define xcalloc guestfs_safe_calloc static void print_strings (char * const* const argv) @@ -8207,70 +8209,70 @@ print_strings (char * const* const argv) pr " char **strs;\n"; pr " int n, i;\n"; pr " sscanf (val, \"%%d\", &n);\n"; - pr " strs = malloc ((n+1) * sizeof (char *));\n"; + pr " strs = xmalloc (g, (n+1) * sizeof (char *));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i] = malloc (16);\n"; + pr " strs[i] = xmalloc (g, 16);\n"; pr " snprintf (strs[i], 16, \"%%d\", i);\n"; pr " }\n"; pr " strs[n] = NULL;\n"; pr " return strs;\n" | RIntBool _ -> pr " struct guestfs_int_bool *r;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = xmalloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%\" SCNi32, &r->i);\n"; pr " r->b = 0;\n"; pr " return r;\n" | RPVList _ -> pr " struct guestfs_lvm_pv_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = xmalloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = xcalloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].pv_name = malloc (16);\n"; + pr " r->val[i].pv_name = xmalloc (g, 16);\n"; pr " snprintf (r->val[i].pv_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RVGList _ -> pr " struct guestfs_lvm_vg_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = xmalloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = xcalloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].vg_name = malloc (16);\n"; + pr " r->val[i].vg_name = xmalloc (g, 16);\n"; pr " snprintf (r->val[i].vg_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RLVList _ -> pr " struct guestfs_lvm_lv_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = xmalloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = xcalloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].lv_name = malloc (16);\n"; + pr " r->val[i].lv_name = xmalloc (g, 16);\n"; pr " snprintf (r->val[i].lv_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RStat _ -> pr " struct guestfs_stat *r;\n"; - pr " r = calloc (1, sizeof (*r));\n"; + pr " r = xcalloc (g, 1, sizeof (*r));\n"; pr " sscanf (val, \"%%\" SCNi64, &r->dev);\n"; pr " return r;\n" | RStatVFS _ -> pr " struct guestfs_statvfs *r;\n"; - pr " r = calloc (1, sizeof (*r));\n"; + pr " r = xcalloc (g, 1, sizeof (*r));\n"; pr " sscanf (val, \"%%\" SCNi64, &r->bsize);\n"; pr " return r;\n" | RHashtable _ -> pr " char **strs;\n"; pr " int n, i;\n"; pr " sscanf (val, \"%%d\", &n);\n"; - pr " strs = malloc ((n*2+1) * sizeof (*strs));\n"; + pr " strs = xmalloc (g, (n*2+1) * sizeof (*strs));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i*2] = malloc (16);\n"; - pr " strs[i*2+1] = malloc (16);\n"; + pr " strs[i*2] = xmalloc (g, 16);\n"; + pr " strs[i*2+1] = xmalloc (g, 16);\n"; pr " snprintf (strs[i*2], 16, \"%%d\", i);\n"; pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n"; pr " }\n"; @@ -8279,9 +8281,9 @@ print_strings (char * const* const argv) | RDirentList _ -> pr " struct guestfs_dirent_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = xmalloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = xcalloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i)\n"; pr " r->val[i].ino = i;\n"; pr " return r;\n" diff --git a/src/guestfs.c b/src/guestfs.c index c3bce0b..350d848 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -453,6 +454,42 @@ guestfs_safe_malloc (guestfs_h *g, size_t nbytes) return ptr; } +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + +/* Technically we should add an autoconf test for this, testing for the desired + functionality, like what's done in gnulib, but for now, this is fine. */ +#define HAVE_GNU_CALLOC (__GLIBC__ >= 2) + +/* Allocate zeroed memory for N elements of S bytes, with error + checking. S must be nonzero. */ +void * +guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s) +{ + /* From gnulib's calloc function in xmalloc.c. */ + void *p; + /* Test for overflow, since some calloc implementations don't have + proper overflow checks. But omit overflow and size-zero tests if + HAVE_GNU_CALLOC, since GNU calloc catches overflow and never + returns NULL if successful. */ + if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s)) + || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0))) + g->abort_cb (); + return p; +} + void * guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes) { diff --git a/src/guestfs.h b/src/guestfs.h index 201d60c..264986f 100644 --- a/src/guestfs.h +++ b/src/guestfs.h @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -77,6 +77,7 @@ extern void guestfs_error (guestfs_h *g, const char *fs, ...) extern void guestfs_perrorf (guestfs_h *g, const char *fs, ...) __attribute__((format (printf,2,3))); extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes); +extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s); extern void *guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes); extern char *guestfs_safe_strdup (guestfs_h *g, const char *str); extern void *guestfs_safe_memdup (guestfs_h *g, void *ptr, size_t size); -- 1.6.3.3.507.gc6b5a From rjones at redhat.com Thu Jul 2 21:21:23 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 22:21:23 +0100 Subject: [fedora-virt] [PATCH libguestfs] use xmalloc and xcalloc in generated code In-Reply-To: <87tz1uss3u.fsf@meyering.net> References: <87tz1uss3u.fsf@meyering.net> Message-ID: <20090702212123.GA27085@amd.home.annexia.org> On Thu, Jul 02, 2009 at 11:16:37PM +0200, Jim Meyering wrote: > Hi Rich, > > I noticed that there were some unchecked malloc and calloc return values. > That could result in NULL deref upon failed allocation. Based on what > you said about there not being much point in trying to recover from OOM > errors, I made the small textual change to convert e.g., malloc(n) to > xmalloc(g,n) where xmalloc now ends up calling g->abort_cb upon malloc > failure. Then any following dereference of the result is guaranteed to > be valid. I think the patch is fine, but I generally wonder why we now have functions which do the same thing called xmalloc and [guestfs_]safe_malloc? Rich. From jim at meyering.net Thu Jul 2 22:19:48 2009 From: jim at meyering.net (Jim Meyering) Date: Fri, 03 Jul 2009 00:19:48 +0200 Subject: [fedora-virt] [PATCH libguestfs] use xmalloc and xcalloc in generated code In-Reply-To: <20090702212123.GA27085@amd.home.annexia.org> (Richard W. M. Jones's message of "Thu, 2 Jul 2009 22:21:23 +0100") References: <87tz1uss3u.fsf@meyering.net> <20090702212123.GA27085@amd.home.annexia.org> Message-ID: <87ocs2sp6j.fsf@meyering.net> Richard W.M. Jones wrote: > On Thu, Jul 02, 2009 at 11:16:37PM +0200, Jim Meyering wrote: >> Hi Rich, >> >> I noticed that there were some unchecked malloc and calloc return values. >> That could result in NULL deref upon failed allocation. Based on what >> you said about there not being much point in trying to recover from OOM >> errors, I made the small textual change to convert e.g., malloc(n) to >> xmalloc(g,n) where xmalloc now ends up calling g->abort_cb upon malloc >> failure. Then any following dereference of the result is guaranteed to >> be valid. > > I think the patch is fine, but I generally wonder why we now have > functions which do the same thing called xmalloc and > [guestfs_]safe_malloc? I've adjusted to use only safe_malloc and safe_calloc, instead of xmalloc and xcalloc. With this, rebased against the latest, all tests pass and duration is 20m, much better than the recent 33m, yet slightly worse than pre-virtio time of 15m. >From 447dae7df43e8a98da59d94f1aef9895e087aa13 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 2 Jul 2009 15:39:08 +0200 Subject: [PATCH] use safe_malloc and safe_calloc in generated code * src/generator.ml (safe_malloc): Define to guestfs_safe_malloc. (safe_calloc): Define to guestfs_safe_calloc. [most generated code]: Fail immediately upon failure of otherwise- unchecked malloc and calloc calls. * src/guestfs.c: Include . (xalloc_oversized): Define. * src/guestfs.h (guestfs_safe_calloc): Declare. --- src/generator.ml | 44 +++++++++++++++++++++++--------------------- src/guestfs.c | 39 ++++++++++++++++++++++++++++++++++++++- src/guestfs.h | 3 ++- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/generator.ml b/src/generator.ml index 4b7efa0..c65e717 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -121,7 +121,7 @@ type flags = | NotInDocs (* do not add this function to documentation *) let protocol_limit_warning = - "Because of the message protocol, there is a transfer limit + "Because of the message protocol, there is a transfer limit of somewhere between 2MB and 4MB. To transfer large files you should use FTP." @@ -6396,7 +6396,7 @@ Sys::Guestfs - Perl bindings for libguestfs =head1 SYNOPSIS use Sys::Guestfs; - + my $h = Sys::Guestfs->new (); $h->add_drive ('guest.img'); $h->launch (); @@ -8144,6 +8144,8 @@ and generate_bindtests () = #include \"guestfs_protocol.h\" #define error guestfs_error +#define safe_calloc guestfs_safe_calloc +#define safe_malloc guestfs_safe_malloc static void print_strings (char * const* const argv) @@ -8219,70 +8221,70 @@ print_strings (char * const* const argv) pr " char **strs;\n"; pr " int n, i;\n"; pr " sscanf (val, \"%%d\", &n);\n"; - pr " strs = malloc ((n+1) * sizeof (char *));\n"; + pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i] = malloc (16);\n"; + pr " strs[i] = safe_malloc (g, 16);\n"; pr " snprintf (strs[i], 16, \"%%d\", i);\n"; pr " }\n"; pr " strs[n] = NULL;\n"; pr " return strs;\n" | RIntBool _ -> pr " struct guestfs_int_bool *r;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = safe_malloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%\" SCNi32, &r->i);\n"; pr " r->b = 0;\n"; pr " return r;\n" | RPVList _ -> pr " struct guestfs_lvm_pv_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = safe_malloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].pv_name = malloc (16);\n"; + pr " r->val[i].pv_name = safe_malloc (g, 16);\n"; pr " snprintf (r->val[i].pv_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RVGList _ -> pr " struct guestfs_lvm_vg_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = safe_malloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].vg_name = malloc (16);\n"; + pr " r->val[i].vg_name = safe_malloc (g, 16);\n"; pr " snprintf (r->val[i].vg_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RLVList _ -> pr " struct guestfs_lvm_lv_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = safe_malloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i) {\n"; - pr " r->val[i].lv_name = malloc (16);\n"; + pr " r->val[i].lv_name = safe_malloc (g, 16);\n"; pr " snprintf (r->val[i].lv_name, 16, \"%%d\", i);\n"; pr " }\n"; pr " return r;\n" | RStat _ -> pr " struct guestfs_stat *r;\n"; - pr " r = calloc (1, sizeof (*r));\n"; + pr " r = safe_calloc (g, 1, sizeof (*r));\n"; pr " sscanf (val, \"%%\" SCNi64, &r->dev);\n"; pr " return r;\n" | RStatVFS _ -> pr " struct guestfs_statvfs *r;\n"; - pr " r = calloc (1, sizeof (*r));\n"; + pr " r = safe_calloc (g, 1, sizeof (*r));\n"; pr " sscanf (val, \"%%\" SCNi64, &r->bsize);\n"; pr " return r;\n" | RHashtable _ -> pr " char **strs;\n"; pr " int n, i;\n"; pr " sscanf (val, \"%%d\", &n);\n"; - pr " strs = malloc ((n*2+1) * sizeof (*strs));\n"; + pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n"; pr " for (i = 0; i < n; ++i) {\n"; - pr " strs[i*2] = malloc (16);\n"; - pr " strs[i*2+1] = malloc (16);\n"; + pr " strs[i*2] = safe_malloc (g, 16);\n"; + pr " strs[i*2+1] = safe_malloc (g, 16);\n"; pr " snprintf (strs[i*2], 16, \"%%d\", i);\n"; pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n"; pr " }\n"; @@ -8291,9 +8293,9 @@ print_strings (char * const* const argv) | RDirentList _ -> pr " struct guestfs_dirent_list *r;\n"; pr " int i;\n"; - pr " r = malloc (sizeof *r);\n"; + pr " r = safe_malloc (g, sizeof *r);\n"; pr " sscanf (val, \"%%d\", &r->len);\n"; - pr " r->val = calloc (r->len, sizeof *r->val);\n"; + pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n"; pr " for (i = 0; i < r->len; ++i)\n"; pr " r->val[i].ino = i;\n"; pr " return r;\n" diff --git a/src/guestfs.c b/src/guestfs.c index c3bce0b..350d848 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -453,6 +454,42 @@ guestfs_safe_malloc (guestfs_h *g, size_t nbytes) return ptr; } +/* Return 1 if an array of N objects, each of size S, cannot exist due + to size arithmetic overflow. S must be positive and N must be + nonnegative. This is a macro, not an inline function, so that it + works correctly even when SIZE_MAX < N. + + By gnulib convention, SIZE_MAX represents overflow in size + calculations, so the conservative dividend to use here is + SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. + However, malloc (SIZE_MAX) fails on all known hosts where + sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for + exactly-SIZE_MAX allocations on such hosts; this avoids a test and + branch when S is known to be 1. */ +# define xalloc_oversized(n, s) \ + ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) + +/* Technically we should add an autoconf test for this, testing for the desired + functionality, like what's done in gnulib, but for now, this is fine. */ +#define HAVE_GNU_CALLOC (__GLIBC__ >= 2) + +/* Allocate zeroed memory for N elements of S bytes, with error + checking. S must be nonzero. */ +void * +guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s) +{ + /* From gnulib's calloc function in xmalloc.c. */ + void *p; + /* Test for overflow, since some calloc implementations don't have + proper overflow checks. But omit overflow and size-zero tests if + HAVE_GNU_CALLOC, since GNU calloc catches overflow and never + returns NULL if successful. */ + if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s)) + || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0))) + g->abort_cb (); + return p; +} + void * guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes) { diff --git a/src/guestfs.h b/src/guestfs.h index 201d60c..264986f 100644 --- a/src/guestfs.h +++ b/src/guestfs.h @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -77,6 +77,7 @@ extern void guestfs_error (guestfs_h *g, const char *fs, ...) extern void guestfs_perrorf (guestfs_h *g, const char *fs, ...) __attribute__((format (printf,2,3))); extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes); +extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s); extern void *guestfs_safe_realloc (guestfs_h *g, void *ptr, int nbytes); extern char *guestfs_safe_strdup (guestfs_h *g, const char *str); extern void *guestfs_safe_memdup (guestfs_h *g, void *ptr, size_t size); -- 1.6.3.3.507.gc6b5a From rjones at redhat.com Thu Jul 2 22:23:18 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 23:23:18 +0100 Subject: [fedora-virt] libguestfs 1.0.55 released Message-ID: <20090702222318.GB27085@amd.home.annexia.org> We are very pleased to announce release 1.0.55 of libguestfs, the library for accessing and modifying virtual machine disk images. Home page: http://libguestfs.org/ Download: http://libguestfs.org/download/libguestfs-1.0.55.tar.gz Thanks go to Guido Gunther, Matt Booth and Jim Meyering for their contributions, and Charles Duffy, Yaakov Nemoy and SALstar for pointing out bugs and misc fixes. The number of changes in 1.0.55 (even over the previous release 3 days ago) is large, and compared to earlier versions we've added dozens of extra commands and features. The best thing to do is to refer to the copious changelog: http://git.et.redhat.com/?p=libguestfs.git;a=log A brief list of the highlights: - Debian native (debootstrap, debirf) support - guestfish -i (use libvirt+virt-inspector to mount partitions) - #!/usr/bin/guestfish -f (for scripts) - new, simpler partitioning command 'sfdiskM' - guestfish commands: time, glob, more, less - removal of the generated code from the git repo - new commands: readdir, mknod*, umask, du, df*, head*, tail*, wc*, mkdtemp, scrub, sh, sh-lines. - many improvements to virt-inspector and YAML output - loopback mounts in the guest now work For this release we were intending to switch to using virtio block devices[1], but hit a performance regression[2]. Although we think we have solved the performance problem, this release still defaults to using emulated IDE devices, but you can try out virtio by using './configure --with-drive-if=virtio'. In future we intend to switch to using virtio by default, but packagers will still be able to choose to use IDE (or SCSI) with the --with-drive-if option. [1]http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=4513f2ec7b6aa843005ba886cdd1747b6ff00915 [2]https://bugzilla.redhat.com/show_bug.cgi?id=509383 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 75 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora From rjones at redhat.com Thu Jul 2 22:26:38 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 2 Jul 2009 23:26:38 +0100 Subject: [fedora-virt] [PATCH libguestfs] use xmalloc and xcalloc in generated code In-Reply-To: <87ocs2sp6j.fsf@meyering.net> References: <87tz1uss3u.fsf@meyering.net> <20090702212123.GA27085@amd.home.annexia.org> <87ocs2sp6j.fsf@meyering.net> Message-ID: <20090702222638.GB26887@amd.home.annexia.org> On Fri, Jul 03, 2009 at 12:19:48AM +0200, Jim Meyering wrote: > Richard W.M. Jones wrote: > > I think the patch is fine, but I generally wonder why we now have > > functions which do the same thing called xmalloc and > > [guestfs_]safe_malloc? > > I've adjusted to use only safe_malloc and safe_calloc, > instead of xmalloc and xcalloc. With this, rebased against > the latest, all tests pass and duration is 20m, much better than > the recent 33m, yet slightly worse than pre-virtio time of 15m. This will probably be because of: https://bugzilla.redhat.com/show_bug.cgi?id=509383#c3 > [the patch] +1 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From pasik at iki.fi Fri Jul 3 10:16:53 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Fri, 3 Jul 2009 13:16:53 +0300 Subject: [fedora-virt] Forward-ported Xen dom0 kernel patches for Linux 2.6.29 and 2.6.30 available Message-ID: <20090703101653.GS24960@edu.joroinen.fi> Hello! For reference here are the latest Xenlinux 2.6.18 forward-ported patches to standard/kernel.org Linux 2.6.29 and 2.6.30. Forward-porting has been done by Novell for OpenSUSE. Novell also has a forward-port to 2.6.27 for SLES11. See this thread for the latest patches: http://www.nabble.com/2.6.30-dom0-Xen-patches-td24293721.html Patches for 2.6.29 and 2.6.30 available here: http://code.google.com/p/gentoo-xen-kernel/downloads/list Also available here: http://x17.eu/xen/ Someone interested in building Xen dom0 capable kernel for F11, based on these patches? These patches are still more stable and mature than the pv_ops dom0 code.. Also, these patches have the full Xen feature set (pv_ops still lacks some features). If you have any problems with these patches, please post to xen-devel mailinglist. -- Pasi From rjones at redhat.com Fri Jul 3 11:07:11 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 12:07:11 +0100 Subject: [fedora-virt] guestfish: Tab completion on destination paths Message-ID: <20090703110711.GA30950@amd.home.annexia.org> I just pushed this: http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=2018441f426aac5a6e48fc6d7cf8155122706215 It should provide tab completion on destination paths, partitions and LV names, and in my limited testing it works OK. However because this is a major change to the interactive use of guestfish, it's possible it will break things. Please try it out, and if you get any sort of failure/segfault in guestfish, let us know. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Fri Jul 3 11:12:03 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 12:12:03 +0100 Subject: [fedora-virt] Re: [PATCH] allow to build Debian based appliance In-Reply-To: <20090703110020.GA20803@bogon.sigxcpu.org> References: <20090702111559.GA24243@bogon.sigxcpu.org> <20090703095200.GA30521@amd.home.annexia.org> <20090703110020.GA20803@bogon.sigxcpu.org> Message-ID: <20090703111203.GA30973@amd.home.annexia.org> On Fri, Jul 03, 2009 at 01:00:20PM +0200, Guido G?nther wrote: > On Fri, Jul 03, 2009 at 10:52:00AM +0100, Richard W.M. Jones wrote: > > > > Guido, please see if this cset fixes your issue: > > > > http://git.et.redhat.com/?p=libguestfs.git;a=commitdiff;h=a67c46b4b2ff5a2c4305e39d1bb105b658ca5f89 > > > Thanks! Looks good. While looking at this, I noticed that we can easily > drop some of the debirf scripts. Possible patch attached. > The remaining symlinks don't contain much. I could put them into one > script so we don't have to ship any symlinks if you'd prefer that? > > The second patch attached touches fakeroot.log (which is what's checked > by applicance/Makefile) so the appliance doesn't get rebuild every time. I pushed both of these patches. Rich. > >From 8eee4dea4c705d3156ac31356565a8f9b30c2f8d Mon Sep 17 00:00:00 2001 > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Fri, 3 Jul 2009 12:42:38 +0200 > Subject: [PATCH] remove superflous debirf scripts > > --- > appliance/Makefile.am | 4 ---- > appliance/debian/modules/a0_motd | 1 - > appliance/debian/modules/network | 1 - > appliance/debian/modules/root-bashrc | 1 - > appliance/debian/modules/serial-terminal | 1 - > 5 files changed, 0 insertions(+), 8 deletions(-) > delete mode 120000 appliance/debian/modules/a0_motd > delete mode 120000 appliance/debian/modules/network > delete mode 120000 appliance/debian/modules/root-bashrc > delete mode 120000 appliance/debian/modules/serial-terminal > > diff --git a/appliance/Makefile.am b/appliance/Makefile.am > index 9de11cd..ff75a67 100644 > --- a/appliance/Makefile.am > +++ b/appliance/Makefile.am > @@ -98,11 +98,7 @@ endif > > # Extra symlinks needed by the Debian appliance. > debirf_symlinks = \ > - a0_motd \ > a0_prep-root \ > - network \ > - root-bashrc \ > - serial-terminal \ > z0_remove-aptitude \ > z0_remove-locales \ > z1_clean-root > diff --git a/appliance/debian/modules/a0_motd b/appliance/debian/modules/a0_motd > deleted file mode 120000 > index 8e3ad2f..0000000 > --- a/appliance/debian/modules/a0_motd > +++ /dev/null > @@ -1 +0,0 @@ > -/usr/share/debirf/modules/a0_motd > \ No newline at end of file > diff --git a/appliance/debian/modules/network b/appliance/debian/modules/network > deleted file mode 120000 > index 979418d..0000000 > --- a/appliance/debian/modules/network > +++ /dev/null > @@ -1 +0,0 @@ > -/usr/share/debirf/modules/network > \ No newline at end of file > diff --git a/appliance/debian/modules/root-bashrc b/appliance/debian/modules/root-bashrc > deleted file mode 120000 > index 651d030..0000000 > --- a/appliance/debian/modules/root-bashrc > +++ /dev/null > @@ -1 +0,0 @@ > -/usr/share/debirf/modules/root-bashrc > \ No newline at end of file > diff --git a/appliance/debian/modules/serial-terminal b/appliance/debian/modules/serial-terminal > deleted file mode 120000 > index a5376da..0000000 > --- a/appliance/debian/modules/serial-terminal > +++ /dev/null > @@ -1 +0,0 @@ > -/usr/share/debirf/modules/serial-terminal > \ No newline at end of file > -- > 1.6.3.3 > > From: =?utf-8?q?Guido=20G=C3=BCnther?= > Date: Thu, 2 Jul 2009 17:30:40 +0200 > Subject: [PATCH] touch fakeroot.log > > indicationg we're done creating the appliance > --- > appliance/make.sh.in | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/appliance/make.sh.in b/appliance/make.sh.in > index e98c325..dd36bb4 100755 > --- a/appliance/make.sh.in > +++ b/appliance/make.sh.in > @@ -148,5 +148,7 @@ __EOF__ > elif [ "@DIST@" = "DEBIAN" ]; then > cd @top_builddir@/appliance > debirf make -n debian > + mkdir -p @top_builddir@/initramfs > + touch @top_builddir@/initramfs/fakeroot.log > fi > > -- -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From mbooth at redhat.com Fri Jul 3 11:42:20 2009 From: mbooth at redhat.com (Matthew Booth) Date: Fri, 03 Jul 2009 12:42:20 +0100 Subject: [fedora-virt] [PATCH] Make it possible to build in a separate directory Message-ID: <4A4DEE9C.6060606@redhat.com> Attached fixes up some build related things. Note that I'm not convinced that the debirf will work if the build directory isn't the top level, and I haven't been able to test. However, the behaviour shouldn't be changed if you aren't using a separate build directory. Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-Make-it-possible-to-build-in-a-separate-directory.patch URL: From mbooth at redhat.com Fri Jul 3 12:50:33 2009 From: mbooth at redhat.com (Matthew Booth) Date: Fri, 03 Jul 2009 13:50:33 +0100 Subject: [fedora-virt] [PATCH] Remove receive callbacks Message-ID: <4A4DFE99.70302@redhat.com> This is a repost of my previous patch, rebased against the current head. Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: 0001-Remove-receive-callbacks.patch URL: From jim at meyering.net Fri Jul 3 13:10:17 2009 From: jim at meyering.net (Jim Meyering) Date: Fri, 03 Jul 2009 15:10:17 +0200 Subject: [fedora-virt] [PATCH libguestfs] daemon/readdir: avoid a small leak Message-ID: <87fxddq5dy.fsf@meyering.net> >From 1b85f07c6aa5f4877ac066aed9c2341782b7f1fe Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 3 Jul 2009 11:52:19 +0200 Subject: [PATCH libguestfs] daemon/readdir: avoid a small leak * daemon/readdir.c (do_readdir): Free both p and v.name, in case only one of the allocations failed. --- daemon/readdir.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/daemon/readdir.c b/daemon/readdir.c index cea6fdd..38bc66e 100644 --- a/daemon/readdir.c +++ b/daemon/readdir.c @@ -68,6 +68,8 @@ do_readdir (char *path) if (!p || !v.name) { reply_with_perror ("allocate"); free (ret->guestfs_int_dirent_list_val); + free (p); + free (v.name); free (ret); closedir (dir); return NULL; -- 1.6.3.3.507.gc6b5a From jim at meyering.net Fri Jul 3 13:11:47 2009 From: jim at meyering.net (Jim Meyering) Date: Fri, 03 Jul 2009 15:11:47 +0200 Subject: [fedora-virt] [PATCH libguestfs] remove trailing blanks Message-ID: <87ab3lq5bg.fsf@meyering.net> Hi Rich, What do you think about this? I was slightly annoyed to see occasional trailing blanks being highlighted. This removes them all: git grep -a -l '[[:blank:]]$' | grep -v -E '\.(gif|png|jpg|rpm)$' \ | xargs perl -pi -e 's/[ \t]+$//' >From 840056c7e5b51462aa8c959bbaa58e6c392daa92 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 3 Jul 2009 11:53:49 +0200 Subject: [PATCH libguestfs] remove trailing blanks --- ABOUT-NLS | 6 +++--- daemon/augeas.c | 2 +- daemon/blockdev.c | 2 +- daemon/checksum.c | 2 +- daemon/cmp.c | 2 +- daemon/command.c | 2 +- daemon/cpmv.c | 2 +- daemon/debug.c | 2 +- daemon/devsparts.c | 2 +- daemon/df.c | 2 +- daemon/dir.c | 2 +- daemon/dmesg.c | 2 +- daemon/dropcaches.c | 2 +- daemon/du.c | 2 +- daemon/ext2.c | 2 +- daemon/file.c | 2 +- daemon/find.c | 2 +- daemon/fsck.c | 2 +- daemon/glob.c | 2 +- daemon/grub.c | 2 +- daemon/guestfsd.c | 2 +- daemon/headtail.c | 2 +- daemon/hexdump.c | 2 +- daemon/initrd.c | 2 +- daemon/ls.c | 2 +- daemon/lvm.c | 2 +- daemon/mknod.c | 2 +- daemon/mount.c | 2 +- daemon/ntfs.c | 2 +- daemon/pingdaemon.c | 2 +- daemon/proto.c | 2 +- daemon/readdir.c | 2 +- daemon/scrub.c | 2 +- daemon/sfdisk.c | 2 +- daemon/sleep.c | 2 +- daemon/stat.c | 2 +- daemon/strings.c | 2 +- daemon/swap.c | 2 +- daemon/sync.c | 2 +- daemon/tar.c | 2 +- daemon/umask.c | 2 +- daemon/upload.c | 2 +- daemon/wc.c | 2 +- daemon/zero.c | 2 +- daemon/zerofree.c | 2 +- fish/alloc.c | 2 +- fish/echo.c | 2 +- fish/edit.c | 2 +- fish/fish.c | 2 +- fish/glob.c | 2 +- fish/lcd.c | 2 +- fish/more.c | 2 +- fish/time.c | 2 +- guestfish.pod | 6 +++--- guestfs.pod | 14 +++++++------- inspector/virt-inspector.pl | 2 +- libguestfs.pc.in | 2 +- m4/intltool.m4 | 32 ++++++++++++++++---------------- m4/intmax.m4 | 2 +- ocaml/.depend | 10 +++++----- recipes/clone.example | 2 +- recipes/export2tar.example | 4 ++-- recipes/iso2tar.example | 2 +- regressions/test-cleanup.sh | 1 - 64 files changed, 93 insertions(+), 94 deletions(-) diff --git a/ABOUT-NLS b/ABOUT-NLS index 2f50c66..18386f0 100644 --- a/ABOUT-NLS +++ b/ABOUT-NLS @@ -319,7 +319,7 @@ translation percentage of at least 50%. +----------------------------------------------------+ af am ar az be bg bs ca cs da de el en en_GB eo es 4 0 0 1 9 4 1 40 41 60 78 17 1 5 13 68 - + et eu fa fi fr ga gl he hr hu id is it ja ko lg +-------------------------------------------------+ a2ps | [] [] [] () () | @@ -456,7 +456,7 @@ translation percentage of at least 50%. +-------------------------------------------------+ et eu fa fi fr ga gl he hr hu id is it ja ko lg 22 2 1 26 106 28 24 8 10 41 33 1 26 33 12 0 - + lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru +-----------------------------------------------------+ a2ps | [] [] () () [] [] [] | @@ -593,7 +593,7 @@ translation percentage of at least 50%. +-----------------------------------------------------+ lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru 1 2 0 3 12 0 10 69 6 7 1 40 26 36 76 63 - + sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu +-----------------------------------------------------+ a2ps | [] [] [] [] | 16 diff --git a/daemon/augeas.c b/daemon/augeas.c index 9b45f97..383812f 100644 --- a/daemon/augeas.c +++ b/daemon/augeas.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/blockdev.c b/daemon/blockdev.c index 1b0185a..35d14bf 100644 --- a/daemon/blockdev.c +++ b/daemon/blockdev.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/checksum.c b/daemon/checksum.c index 3654b65..bb30b05 100644 --- a/daemon/checksum.c +++ b/daemon/checksum.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/cmp.c b/daemon/cmp.c index 04feba6..f650083 100644 --- a/daemon/cmp.c +++ b/daemon/cmp.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/command.c b/daemon/command.c index b33f2db..3f21807 100644 --- a/daemon/command.c +++ b/daemon/command.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/cpmv.c b/daemon/cpmv.c index b87d7a4..5448a97 100644 --- a/daemon/cpmv.c +++ b/daemon/cpmv.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/debug.c b/daemon/debug.c index d6e469b..68320a3 100644 --- a/daemon/debug.c +++ b/daemon/debug.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/devsparts.c b/daemon/devsparts.c index 4c7a643..32d2fa8 100644 --- a/daemon/devsparts.c +++ b/daemon/devsparts.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/df.c b/daemon/df.c index 0a7303c..73604b4 100644 --- a/daemon/df.c +++ b/daemon/df.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/dir.c b/daemon/dir.c index 753323d..6eb86bb 100644 --- a/daemon/dir.c +++ b/daemon/dir.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/dmesg.c b/daemon/dmesg.c index 2e58eb9..adc3426 100644 --- a/daemon/dmesg.c +++ b/daemon/dmesg.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/dropcaches.c b/daemon/dropcaches.c index 82d95ee..a818323 100644 --- a/daemon/dropcaches.c +++ b/daemon/dropcaches.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/du.c b/daemon/du.c index 6287a20..6f1adba 100644 --- a/daemon/du.c +++ b/daemon/du.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/ext2.c b/daemon/ext2.c index c5e1415..5a1d0fd 100644 --- a/daemon/ext2.c +++ b/daemon/ext2.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/file.c b/daemon/file.c index 3f07ffc..3ef7441 100644 --- a/daemon/file.c +++ b/daemon/file.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/find.c b/daemon/find.c index 7ceeafa..85994b6 100644 --- a/daemon/find.c +++ b/daemon/find.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/fsck.c b/daemon/fsck.c index 77e7c66..f1a9dc5 100644 --- a/daemon/fsck.c +++ b/daemon/fsck.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/glob.c b/daemon/glob.c index f39832e..f15d5e5 100644 --- a/daemon/glob.c +++ b/daemon/glob.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/grub.c b/daemon/grub.c index 85a5ab9..29fe294 100644 --- a/daemon/grub.c +++ b/daemon/grub.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index e5f2cf0..581c82e 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/headtail.c b/daemon/headtail.c index b522c55..6d24851 100644 --- a/daemon/headtail.c +++ b/daemon/headtail.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/hexdump.c b/daemon/hexdump.c index ae7df92..a582c57 100644 --- a/daemon/hexdump.c +++ b/daemon/hexdump.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/initrd.c b/daemon/initrd.c index 2d6cbdd..7b32a08 100644 --- a/daemon/initrd.c +++ b/daemon/initrd.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/ls.c b/daemon/ls.c index 61055b6..a440080 100644 --- a/daemon/ls.c +++ b/daemon/ls.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/lvm.c b/daemon/lvm.c index 0fba447..b81badb 100644 --- a/daemon/lvm.c +++ b/daemon/lvm.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/mknod.c b/daemon/mknod.c index 5af791f..315ea7d 100644 --- a/daemon/mknod.c +++ b/daemon/mknod.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/mount.c b/daemon/mount.c index b0cb496..1820f8a 100644 --- a/daemon/mount.c +++ b/daemon/mount.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/ntfs.c b/daemon/ntfs.c index 87881b1..26c8d50 100644 --- a/daemon/ntfs.c +++ b/daemon/ntfs.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/pingdaemon.c b/daemon/pingdaemon.c index 5417a1d..0a69afa 100644 --- a/daemon/pingdaemon.c +++ b/daemon/pingdaemon.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/proto.c b/daemon/proto.c index 3ca4316..62871b5 100644 --- a/daemon/proto.c +++ b/daemon/proto.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/readdir.c b/daemon/readdir.c index 38bc66e..e3851db 100644 --- a/daemon/readdir.c +++ b/daemon/readdir.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/scrub.c b/daemon/scrub.c index 9b6d49d..2f14bcb 100644 --- a/daemon/scrub.c +++ b/daemon/scrub.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/sfdisk.c b/daemon/sfdisk.c index f1726fc..f512e26 100644 --- a/daemon/sfdisk.c +++ b/daemon/sfdisk.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/sleep.c b/daemon/sleep.c index 2cf3ff7..3b5d395 100644 --- a/daemon/sleep.c +++ b/daemon/sleep.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/stat.c b/daemon/stat.c index 6b12f4c..da360ce 100644 --- a/daemon/stat.c +++ b/daemon/stat.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/strings.c b/daemon/strings.c index d78f9fd..2c52532 100644 --- a/daemon/strings.c +++ b/daemon/strings.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/swap.c b/daemon/swap.c index 7dac96e..faed7f6 100644 --- a/daemon/swap.c +++ b/daemon/swap.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/sync.c b/daemon/sync.c index 70962df..b353b6c 100644 --- a/daemon/sync.c +++ b/daemon/sync.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/tar.c b/daemon/tar.c index 0320604..9540827 100644 --- a/daemon/tar.c +++ b/daemon/tar.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/umask.c b/daemon/umask.c index ad8573d..22d2cc9 100644 --- a/daemon/umask.c +++ b/daemon/umask.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/upload.c b/daemon/upload.c index 0f737af..6c5f6dc 100644 --- a/daemon/upload.c +++ b/daemon/upload.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/wc.c b/daemon/wc.c index 91e1942..370ffdd 100644 --- a/daemon/wc.c +++ b/daemon/wc.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/zero.c b/daemon/zero.c index 9d793e1..9c803d8 100644 --- a/daemon/zero.c +++ b/daemon/zero.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/daemon/zerofree.c b/daemon/zerofree.c index ed7a3fc..8000bb3 100644 --- a/daemon/zerofree.c +++ b/daemon/zerofree.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/alloc.c b/fish/alloc.c index cdce73c..a7d115a 100644 --- a/fish/alloc.c +++ b/fish/alloc.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/echo.c b/fish/echo.c index b4b5cf1..33992d4 100644 --- a/fish/echo.c +++ b/fish/echo.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/edit.c b/fish/edit.c index c72ad1d..3e6973e 100644 --- a/fish/edit.c +++ b/fish/edit.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/fish.c b/fish/fish.c index 59348c3..b905c55 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/glob.c b/fish/glob.c index a8ac58a..581bc28 100644 --- a/fish/glob.c +++ b/fish/glob.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/lcd.c b/fish/lcd.c index 359d178..e631f21 100644 --- a/fish/lcd.c +++ b/fish/lcd.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/more.c b/fish/more.c index 8bc9d95..9abb51b 100644 --- a/fish/more.c +++ b/fish/more.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fish/time.c b/fish/time.c index d2a2066..aae9afe 100644 --- a/fish/time.c +++ b/fish/time.c @@ -1,5 +1,5 @@ /* guestfish - the filesystem interactive shell - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/guestfish.pod b/guestfish.pod index 0c3fda6..4341e2a 100644 --- a/guestfish.pod +++ b/guestfish.pod @@ -49,13 +49,13 @@ Remove C (in reality not such a great idea): =head2 As an interactive shell $ guestfish - + Welcome to guestfish, the libguestfs filesystem interactive shell for editing virtual machine filesystems. - + Type: 'help' for help with commands 'quit' to quit the shell - + > help =head2 As a script interpreter diff --git a/guestfs.pod b/guestfs.pod index a41fd27..c7310a6 100644 --- a/guestfs.pod +++ b/guestfs.pod @@ -7,7 +7,7 @@ guestfs - Library for accessing and modifying virtual machine images =head1 SYNOPSIS #include - + guestfs_h *handle = guestfs_create (); guestfs_add_drive (handle, "guest.img"); guestfs_launch (handle); @@ -49,28 +49,28 @@ If you are using the high-level API, then you should call the functions in the following order: guestfs_h *handle = guestfs_create (); - + guestfs_add_drive (handle, "guest.img"); /* call guestfs_add_drive additional times if the guest has * multiple disks */ - + guestfs_launch (handle); guestfs_wait_ready (handle); /* now you can examine what partitions, LVs etc are available * you have to mount / at least - */ + */ guestfs_mount (handle, "/dev/sda1", "/"); /* now you can perform actions on the guest disk image */ guestfs_touch (handle, "/hello"); - + /* you only need to call guestfs_sync if you have made * changes to the guest image */ guestfs_sync (handle); - + guestfs_close (handle); C and all of the actions including C @@ -168,7 +168,7 @@ If you set C to C then I handler is called. Returns the current error handler callback. -=head2 guestfs_set_out_of_memory_handler +=head2 guestfs_set_out_of_memory_handler typedef void (*guestfs_abort_cb) (void); int guestfs_set_out_of_memory_handler (guestfs_h *handle, diff --git a/inspector/virt-inspector.pl b/inspector/virt-inspector.pl index 66b1553..3557a38 100755 --- a/inspector/virt-inspector.pl +++ b/inspector/virt-inspector.pl @@ -968,7 +968,7 @@ elsif ($output eq "perl") { elsif ($output eq "yaml") { die "virt-inspector: no YAML support\n" unless exists $INC{"YAML/Any.pm"}; - + print Dump(\%oses); } diff --git a/libguestfs.pc.in b/libguestfs.pc.in index bcbc241..679ed7e 100644 --- a/libguestfs.pc.in +++ b/libguestfs.pc.in @@ -7,5 +7,5 @@ Name: libguestfs Version: @VERSION@ Description: libguestfs library for accessing and modifying VM images Requires: -Cflags: +Cflags: Libs: -lguestfs @LIBS@ diff --git a/m4/intltool.m4 b/m4/intltool.m4 index 122d773..ba4c0b1 100644 --- a/m4/intltool.m4 +++ b/m4/intltool.m4 @@ -55,23 +55,23 @@ if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) fi - INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' -INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< [$]@' - INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' -INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@' - INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' - INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@' + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' diff --git a/m4/intmax.m4 b/m4/intmax.m4 index dfb08cc..d41188d 100644 --- a/m4/intmax.m4 +++ b/m4/intmax.m4 @@ -16,7 +16,7 @@ AC_DEFUN([gt_TYPE_INTMAX_T], AC_REQUIRE([jm_AC_HEADER_STDINT_H]) AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, [AC_TRY_COMPILE([ -#include +#include #include #if HAVE_STDINT_H_WITH_UINTMAX #include diff --git a/ocaml/.depend b/ocaml/.depend index 5074667..2a582db 100644 --- a/ocaml/.depend +++ b/ocaml/.depend @@ -1,5 +1,5 @@ -guestfs.cmi: -bindtests.cmo: guestfs.cmi -bindtests.cmx: guestfs.cmx -guestfs.cmo: guestfs.cmi -guestfs.cmx: guestfs.cmi +guestfs.cmi: +bindtests.cmo: guestfs.cmi +bindtests.cmx: guestfs.cmx +guestfs.cmo: guestfs.cmi +guestfs.cmx: guestfs.cmi diff --git a/recipes/clone.example b/recipes/clone.example index 40b4df1..3ee96c5 100644 --- a/recipes/clone.example +++ b/recipes/clone.example @@ -11,7 +11,7 @@ editing virtual machine filesystems. Type: 'help' for help with commands 'quit' to quit the shell -> cat /etc/resolv.conf +> cat /etc/resolv.conf nameserver 192.168.1.1 > cat /etc/HOSTNAME newmachine diff --git a/recipes/export2tar.example b/recipes/export2tar.example index 47033c8..7f222f3 100644 --- a/recipes/export2tar.example +++ b/recipes/export2tar.example @@ -1,8 +1,8 @@ $ ./export2tar.sh /dev/mapper/Guests-RHEL53PV32 /dev/VolGroup00/LogVol00 \ /home /tmp/home.tar.gz -$ ll /tmp/home.tar.gz +$ ll /tmp/home.tar.gz -rw-rw-r--. 1 rjones rjones 824 2009-04-25 12:33 /tmp/home.tar.gz -$ tar ztf /tmp/home.tar.gz +$ tar ztf /tmp/home.tar.gz ./ ./rjones/ ./rjones/.bash_profile diff --git a/recipes/iso2tar.example b/recipes/iso2tar.example index 16cb7da..5c796e1 100644 --- a/recipes/iso2tar.example +++ b/recipes/iso2tar.example @@ -1,4 +1,4 @@ -$ ll -h /tmp/Fedora-11-Beta-i386-netinst.iso +$ ll -h /tmp/Fedora-11-Beta-i386-netinst.iso -r--r--r--. 1 rjones rjones 168M 2009-04-25 22:38 /tmp/Fedora-11-Beta-i386-netinst.iso $ ./iso2tar.sh /tmp/Fedora-11-Beta-i386-netinst.iso /tmp/cd.tar.gz $ ls -lh /tmp/cd.tar.gz diff --git a/regressions/test-cleanup.sh b/regressions/test-cleanup.sh index 33194ab..a68f57e 100755 --- a/regressions/test-cleanup.sh +++ b/regressions/test-cleanup.sh @@ -30,4 +30,3 @@ run run ping-daemon EOF - \ No newline at end of file -- 1.6.3.3.507.gc6b5a From jim at meyering.net Fri Jul 3 13:12:49 2009 From: jim at meyering.net (Jim Meyering) Date: Fri, 03 Jul 2009 15:12:49 +0200 Subject: [fedora-virt] [PATCH libguestfs] avoid leak upon failed realloc Message-ID: <874ottq59q.fsf@meyering.net> Hi again, No big deal, but might as well fix this... >From a4040866dd60c92bb2994f8fd9f0d57b62f1842c Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 3 Jul 2009 12:05:22 +0200 Subject: [PATCH libguestfs] avoid leak upon failed realloc * daemon/guestfsd.c (commandrv): Free original buffer (rather than leaking it) if realloc fails. --- daemon/guestfsd.c | 20 ++++++++++++-------- 1 files changed, 12 insertions(+), 8 deletions(-) diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index 581c82e..87065b9 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -572,19 +572,23 @@ commandrv (char **stdoutput, char **stderror, char * const* const argv) * trailing \n characters from the error buffer (not from stdout). */ if (stdoutput) { - *stdoutput = realloc (*stdoutput, so_size+1); - if (*stdoutput == NULL) { + void *q = realloc (*stdoutput, so_size+1); + if (q == NULL) { perror ("realloc"); - *stdoutput = NULL; - } else + free (*stdoutput); + } + *stdoutput = q; + if (*stdoutput) (*stdoutput)[so_size] = '\0'; } if (stderror) { - *stderror = realloc (*stderror, se_size+1); - if (*stderror == NULL) { + void *q = realloc (*stderror, se_size+1); + if (q == NULL) { perror ("realloc"); - *stderror = NULL; - } else { + free (*stderror); + } + *stderror = q; + if (*stderror) { (*stderror)[se_size] = '\0'; se_size--; while (se_size >= 0 && (*stderror)[se_size] == '\n') -- 1.6.3.3.507.gc6b5a From jim at meyering.net Fri Jul 3 13:21:45 2009 From: jim at meyering.net (Jim Meyering) Date: Fri, 03 Jul 2009 15:21:45 +0200 Subject: [fedora-virt] [PATCH libguestfs] generate slightly more "const-correct" code Message-ID: <87y6r5oqae.fsf@meyering.net> const correctness is nice. These changes exposed no problems and induced no new warnings. >From 4a8c1284e88a3a92377919616e73c65ea68e33ae Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 3 Jul 2009 14:17:23 +0200 Subject: [PATCH libguestfs] generate slightly more "const-correct" code * src/generator.ml: Add a few "const" attributes. --- src/generator.ml | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/generator.ml b/src/generator.ml index c65e717..5c9e1c3 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -4686,7 +4686,7 @@ and generate_one_test_body name i test_name init test = List.iter (generate_test_command_call test_name) seq | TestOutput (seq, expected) -> pr " /* TestOutput for %s (%d) */\n" name i; - pr " char expected[] = \"%s\";\n" (c_quote expected); + pr " const char *expected = \"%s\";\n" (c_quote expected); let seq, last = get_seq_last seq in let test () = pr " if (strcmp (r, expected) != 0) {\n"; @@ -4708,7 +4708,7 @@ and generate_one_test_body name i test_name init test = pr " return -1;\n"; pr " }\n"; pr " {\n"; - pr " char expected[] = \"%s\";\n" (c_quote str); + pr " const char *expected = \"%s\";\n" (c_quote str); pr " if (strcmp (r[%d], expected) != 0) {\n" i; pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i; pr " return -1;\n"; @@ -4736,7 +4736,7 @@ and generate_one_test_body name i test_name init test = pr " return -1;\n"; pr " }\n"; pr " {\n"; - pr " char expected[] = \"%s\";\n" (c_quote str); + pr " const char *expected = \"%s\";\n" (c_quote str); pr " r[%d][5] = 's';\n" i; pr " if (strcmp (r[%d], expected) != 0) {\n" i; pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i; @@ -4882,7 +4882,7 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd = | OptString n, "NULL" -> () | String n, arg | OptString n, arg -> - pr " char %s[] = \"%s\";\n" n (c_quote arg); + pr " const char *%s = \"%s\";\n" n (c_quote arg); | Int _, _ | Bool _, _ | FileIn _, _ | FileOut _, _ -> () @@ -4890,9 +4890,9 @@ and generate_test_command_call ?(expect_error = false) ?test test_name cmd = let strs = string_split " " arg in iteri ( fun i str -> - pr " char %s_%d[] = \"%s\";\n" n i (c_quote str); + pr " const char *%s_%d = \"%s\";\n" n i (c_quote str); ) strs; - pr " char *%s[] = {\n" n; + pr " const char *%s[] = {\n" n; iteri ( fun i _ -> pr " %s_%d,\n" n i ) strs; -- 1.6.3.3.507.gc6b5a From markmc at redhat.com Fri Jul 3 13:42:52 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 03 Jul 2009 14:42:52 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1246303956.11688.148.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> Message-ID: <1246628572.13604.2.camel@blaa> Hi, Latest updates to virt-preview repo: == qemu == * Fri Jul 3 2009 Mark McLoughlin - 2:0.10.50-8.kvm87 - Prefer sysfs over usbfs for usb passthrough (#508326) == libvirt == * Fri Jul 3 2009 Mark McLoughlin - 0.6.4-4.fc12 - Fix libvirtd crash with bad capabilities data (bug #505635) * Fri Jul 3 2009 Mark McLoughlin - 0.6.4-3.fc12 - Handle shared/readonly image labelling (bug #493692) - Don't unnecessarily try to change a file context (bug #507555) - Don't try to label a disk with no path (e.g. empty cdrom) (bug #499569) Cheers, Mark. From rjones at redhat.com Fri Jul 3 14:33:22 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:33:22 +0100 Subject: [fedora-virt] [PATCH] Make it possible to build in a separate directory In-Reply-To: <4A4DEE9C.6060606@redhat.com> References: <4A4DEE9C.6060606@redhat.com> Message-ID: <20090703143322.GB30950@amd.home.annexia.org> On Fri, Jul 03, 2009 at 12:42:20PM +0100, Matthew Booth wrote: > elif [ "@DIST@" = "DEBIAN" ]; then > - cd @top_builddir@/appliance > + cd @abs_top_builddir@/appliance > debirf make -n debian Unfortunately abs_top_builddir isn't available in whatever ancient version of autotools that EPEL 5 is using. -1 Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From rjones at redhat.com Fri Jul 3 14:37:11 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:37:11 +0100 Subject: [fedora-virt] [PATCH] Remove receive callbacks In-Reply-To: <4A4DFE99.70302@redhat.com> References: <4A4DFE99.70302@redhat.com> Message-ID: <20090703143711.GC30950@amd.home.annexia.org> On Fri, Jul 03, 2009 at 01:50:33PM +0100, Matthew Booth wrote: > This is a repost of my previous patch, rebased against the current head. > > Matt > -- > Matthew Booth, RHCA, RHCSS > Red Hat Engineering, Virtualisation Team > > M: +44 (0)7977 267231 > GPG ID: D33C3490 > GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 > >From 5f57439a6139fa03560cb3a5351eedc2ebe42e19 Mon Sep 17 00:00:00 2001 > From: Matthew Booth > Date: Sat, 27 Jun 2009 22:05:48 +0100 > Subject: [PATCH] Remove receive callbacks > > This patch fixes a class of race conditions characterised by the > following sequence of events: > > LIBRARY DAEMON > send download request > receive download request > respond with download response > start sending file chunks > set reply callback to 'download' > run main loop > > At this stage the download reply callback receives both the download > reply and some file chunks. The current architecture doesn't provide a clean way > to prevent this from happening. > > This patch fixes the above problem by changing the socket receive > handler to do nothing but buffering, and provides 2 new apis: > > guestfs_get_reply > guestfs_free_reply > > These will always de-queue exactly 1 message, which is always what is > wanted. > --- > src/generator.ml | 211 ++++++++---------- > src/guestfs.c | 672 +++++++++++++++++++++++++----------------------------- > src/guestfs.h | 13 +- > 3 files changed, 417 insertions(+), 479 deletions(-) > > diff --git a/src/generator.ml b/src/generator.ml > index c65e717..c64b8c7 100755 > --- a/src/generator.ml > +++ b/src/generator.ml > @@ -3734,83 +3734,6 @@ check_state (guestfs_h *g, const char *caller) > List.iter ( > fun (shortname, style, _, _, _, _, _) -> > let name = "guestfs_" ^ shortname in > - > - (* Generate the context struct which stores the high-level > - * state between callback functions. > - *) > - pr "struct %s_ctx {\n" shortname; > - pr " /* This flag is set by the callbacks, so we know we've done\n"; > - pr " * the callbacks as expected, and in the right sequence.\n"; > - pr " * 0 = not called, 1 = reply_cb called.\n"; > - pr " */\n"; > - pr " int cb_sequence;\n"; > - pr " struct guestfs_message_header hdr;\n"; > - pr " struct guestfs_message_error err;\n"; > - (match fst style with > - | RErr -> () > - | RConstString _ -> > - failwithf "RConstString cannot be returned from a daemon function" > - | RInt _ | RInt64 _ > - | RBool _ | RString _ | RStringList _ > - | RIntBool _ > - | RPVList _ | RVGList _ | RLVList _ > - | RStat _ | RStatVFS _ > - | RHashtable _ > - | RDirentList _ -> > - pr " struct %s_ret ret;\n" name > - ); > - pr "};\n"; > - pr "\n"; > - > - (* Generate the reply callback function. *) > - pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname; > - pr "{\n"; > - pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; > - pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname; > - pr "\n"; > - pr " /* This should definitely not happen. */\n"; > - pr " if (ctx->cb_sequence != 0) {\n"; > - pr " ctx->cb_sequence = 9999;\n"; > - pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - pr "\n"; > - pr " ml->main_loop_quit (ml, g);\n"; > - pr "\n"; > - pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n"; > - pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n"; > - pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n"; > - pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n" > - name; > - pr " return;\n"; > - pr " }\n"; > - pr " goto done;\n"; > - pr " }\n"; > - > - (match fst style with > - | RErr -> () > - | RConstString _ -> > - failwithf "RConstString cannot be returned from a daemon function" > - | RInt _ | RInt64 _ > - | RBool _ | RString _ | RStringList _ > - | RIntBool _ > - | RPVList _ | RVGList _ | RLVList _ > - | RStat _ | RStatVFS _ > - | RHashtable _ > - | RDirentList _ -> > - pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name; > - pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name; > - pr " return;\n"; > - pr " }\n"; > - ); > - > - pr " done:\n"; > - pr " ctx->cb_sequence = 1;\n"; > - pr "}\n\n"; > - > (* Generate the action stub. *) > generate_prototype ~extern:false ~semicolon:false ~newline:true > ~handle:"g" name style; > @@ -3834,15 +3757,27 @@ check_state (guestfs_h *g, const char *caller) > | _ -> pr " struct %s_args args;\n" name > ); > > - pr " struct %s_ctx ctx;\n" shortname; > - pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n"; > + pr " struct guestfs_message_header hdr = {};\n"; > + pr " struct guestfs_message_error err = {};\n"; > + (match fst style with > + | RErr -> () > + | RConstString _ -> > + failwithf "RConstString cannot be returned from a daemon function" > + | RInt _ | RInt64 _ > + | RBool _ | RString _ | RStringList _ > + | RIntBool _ > + | RPVList _ | RVGList _ | RLVList _ > + | RStat _ | RStatVFS _ > + | RHashtable _ > + | RDirentList _ -> > + pr " struct %s_ret ret = {};\n" name > + ); > + > pr " int serial;\n"; > pr "\n"; > pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code; > pr " guestfs_set_busy (g);\n"; > pr "\n"; > - pr " memset (&ctx, 0, sizeof ctx);\n"; > - pr "\n"; > > (* Send the main header and arguments. *) > (match snd style with > @@ -3877,7 +3812,6 @@ check_state (guestfs_h *g, const char *caller) > pr "\n"; > > (* Send any additional files (FileIn) requested. *) > - let need_read_reply_label = ref false in > List.iter ( > function > | FileIn n -> > @@ -3889,83 +3823,130 @@ check_state (guestfs_h *g, const char *caller) > pr " guestfs_end_busy (g);\n"; > pr " return %s;\n" error_code; > pr " }\n"; > - pr " if (r == -2) /* daemon cancelled */\n"; > - pr " goto read_reply;\n"; > - need_read_reply_label := true; > pr " }\n"; > pr "\n"; > | _ -> () > ) (snd style); > > (* Wait for the reply from the remote end. *) > - if !need_read_reply_label then pr " read_reply:\n"; > - pr " guestfs__switch_to_receiving (g);\n"; > - pr " ctx.cb_sequence = 0;\n"; > - pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname; > - pr " (void) ml->main_loop_run (ml, g);\n"; > - pr " guestfs_set_reply_callback (g, NULL, NULL);\n"; > - pr " if (ctx.cb_sequence != 1) {\n"; > - pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " guestfs_reply_t reply;\n"; > + pr "\n"; > + pr " for (;;) {\n"; > + pr " guestfs_get_reply (g, &reply, 1);\n"; > + pr "\n"; > + pr " if (GUESTFS_CANCEL_FLAG == reply.len) {\n"; > + pr " /* This message was delayed from a previous file transaction. */\n"; > + pr " continue;\n"; > + pr " }\n"; > + pr "\n"; > + pr " if (GUESTFS_LAUNCH_FLAG == reply.len) {\n"; > + pr " error (g, \"%%s reply failed, received unexpected launch message\",\n"; > + pr " \"%s\");\n" name; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + pr " }\n"; > + pr "\n"; > + pr " if (0 == reply.len) {\n"; > + pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + pr " }\n"; > + pr "\n"; > + pr " break;\n"; > pr " }\n"; > pr "\n"; > > - pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n" > + pr " if (!xdr_guestfs_message_header (&reply.xdr, &hdr)) {\n"; > + pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + pr "\n"; > + pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n"; > + pr " if (!xdr_guestfs_message_error (&reply.xdr, &err)) {\n"; > + pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n" > + name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + pr " }\n"; > + > + (match fst style with > + | RErr -> () > + | RConstString _ -> > + failwithf "RConstString cannot be returned from a daemon function" > + | RInt _ | RInt64 _ > + | RBool _ | RString _ | RStringList _ > + | RIntBool _ > + | RPVList _ | RVGList _ | RLVList _ > + | RStat _ | RStatVFS _ > + | RHashtable _ > + | RDirentList _ -> > + pr " else if (!xdr_%s_ret (&reply.xdr, &ret)) {\n" name; > + pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name; > + pr " goto recv_error;\n"; > + pr " }\n"; > + ); > + > + pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n" > (String.uppercase shortname); > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " goto recv_error;\n"; > pr " }\n"; > pr "\n"; > > - pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n"; > - pr " error (g, \"%%s\", ctx.err.error_message);\n"; > - pr " free (ctx.err.error_message);\n"; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n"; > + pr " error (g, \"%%s\", err.error_message);\n"; > + pr " free (err.error_message);\n"; > + pr " goto recv_error;\n"; > pr " }\n"; > pr "\n"; > > + pr " guestfs_free_reply (g, &reply);\n\n"; > + > (* Expecting to receive further files (FileOut)? *) > List.iter ( > function > | FileOut n -> > pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n; > - pr " guestfs_end_busy (g);\n"; > - pr " return %s;\n" error_code; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > pr " }\n"; > pr "\n"; > | _ -> () > ) (snd style); > > - pr " guestfs_end_busy (g);\n"; > + pr " guestfs_end_busy (g);\n\n"; > > (match fst style with > | RErr -> pr " return 0;\n" > | RInt n | RInt64 n | RBool n -> > - pr " return ctx.ret.%s;\n" n > + pr " return ret.%s;\n" n > | RConstString _ -> > failwithf "RConstString cannot be returned from a daemon function" > | RString n -> > - pr " return ctx.ret.%s; /* caller will free */\n" n > + pr " return ret.%s; /* caller will free */\n" n > | RStringList n | RHashtable n -> > pr " /* caller will free this, but we need to add a NULL entry */\n"; > - pr " ctx.ret.%s.%s_val =\n" n n; > - pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n; > - pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n" > + pr " ret.%s.%s_val =\n" n n; > + pr " safe_realloc (g, ret.%s.%s_val,\n" n n; > + pr " sizeof (char *) * (ret.%s.%s_len + 1));\n" > n n; > - pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n; > - pr " return ctx.ret.%s.%s_val;\n" n n > + pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n; > + pr " return ret.%s.%s_val;\n" n n > | RIntBool _ -> > pr " /* caller with free this */\n"; > - pr " return safe_memdup (g, &ctx.ret, sizeof (ctx.ret));\n" > + pr " return safe_memdup (g, &ret, sizeof (ret));\n" > | RPVList n | RVGList n | RLVList n > | RStat n | RStatVFS n > | RDirentList n -> > pr " /* caller will free this */\n"; > - pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n > + pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n > ); > > + pr "\n"; > + pr " recv_error:\n"; > + pr " guestfs_free_reply (g, &reply);\n"; > + pr " guestfs_end_busy (g);\n"; > + pr " return %s;\n" error_code; > + > pr "}\n\n" > ) daemon_functions > > diff --git a/src/guestfs.c b/src/guestfs.c > index 350d848..79251ca 100644 > --- a/src/guestfs.c > +++ b/src/guestfs.c > @@ -21,6 +21,7 @@ > #define _BSD_SOURCE /* for mkdtemp, usleep */ > #define _GNU_SOURCE /* for vasprintf, GNU strerror_r, strchrnul */ > > +#include > #include > #include > #include > @@ -78,8 +79,10 @@ > > static void default_error_cb (guestfs_h *g, void *data, const char *msg); > static void stdout_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > -static void sock_read_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > -static void sock_write_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > +static void sock_event (struct guestfs_main_loop *ml, guestfs_h *g, void *data, int watch, int fd, int events); > +static void sock_read (guestfs_h *g); > +static void sock_write (guestfs_h *g); > +static int sock_update_events (guestfs_h *g); > > static void close_handles (void); > > @@ -161,6 +164,9 @@ struct guestfs_h > int stdout_watch; /* Watches qemu stdout for log messages. */ > int sock_watch; /* Watches daemon comm socket. */ > > + int sock_events; /* events we're listening for on the comm > + socket */ > + > char *tmpdir; /* Temporary directory containing socket. */ > > char *qemu_help, *qemu_version; /* Output of qemu -help, qemu -version. */ > @@ -185,21 +191,18 @@ struct guestfs_h > void * error_cb_data; > guestfs_send_cb send_cb; > void * send_cb_data; > - guestfs_reply_cb reply_cb; > - void * reply_cb_data; > guestfs_log_message_cb log_message_cb; > void * log_message_cb_data; > guestfs_subprocess_quit_cb subprocess_quit_cb; > void * subprocess_quit_cb_data; > - guestfs_launch_done_cb launch_done_cb; > - void * launch_done_cb_data; > > /* Main loop used by this handle. */ > guestfs_main_loop *main_loop; > > /* Messages sent and received from the daemon. */ > char *msg_in; > - int msg_in_size, msg_in_allocated; > + size_t msg_in_size, msg_in_pos, msg_in_consumed, msg_in_len; > + > char *msg_out; > int msg_out_size, msg_out_pos; > > @@ -228,6 +231,8 @@ guestfs_create (void) > g->stdout_watch = -1; > g->sock_watch = -1; > > + g->sock_events = 0; > + > g->abort_cb = abort; > g->error_cb = default_error_cb; > g->error_cb_data = NULL; > @@ -265,6 +270,11 @@ guestfs_create (void) > } else > g->memsize = 500; > > + /* Initialise the message receive buffer */ > + g->msg_in_size = GUESTFS_MESSAGE_MAX + sizeof (g->msg_in_len); As in my comment on the previous revision of this patch, why is this not '+ 4'? > + g->msg_in = safe_malloc (g, g->msg_in_size); > + g->msg_in_pos = g->msg_in_consumed = 0; > + > g->main_loop = guestfs_get_default_main_loop (); > > /* Start with large serial numbers so they are easy to spot > @@ -290,9 +300,10 @@ guestfs_create (void) > return g; > > error: > - free (g->path); > - free (g->qemu); > - free (g->append); > + if (g->msg_in) free (g->msg_in); > + if (g->path) free (g->path); > + if (g->qemu) free (g->qemu); > + if (g->append) free (g->append); As in my previous comment, this is wrong. free (NULL) is fine, so you don't need the if statements. Anyway, -1, but I will try out this patch myself next week. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Fri Jul 3 14:37:53 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:37:53 +0100 Subject: [fedora-virt] [PATCH libguestfs] daemon/readdir: avoid a small leak In-Reply-To: <87fxddq5dy.fsf@meyering.net> References: <87fxddq5dy.fsf@meyering.net> Message-ID: <20090703143753.GD30950@amd.home.annexia.org> On Fri, Jul 03, 2009 at 03:10:17PM +0200, Jim Meyering wrote: > > > >From 1b85f07c6aa5f4877ac066aed9c2341782b7f1fe Mon Sep 17 00:00:00 2001 > From: Jim Meyering > Date: Fri, 3 Jul 2009 11:52:19 +0200 > Subject: [PATCH libguestfs] daemon/readdir: avoid a small leak > > * daemon/readdir.c (do_readdir): Free both p and v.name, in case > only one of the allocations failed. > --- > daemon/readdir.c | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/daemon/readdir.c b/daemon/readdir.c > index cea6fdd..38bc66e 100644 > --- a/daemon/readdir.c > +++ b/daemon/readdir.c > @@ -68,6 +68,8 @@ do_readdir (char *path) > if (!p || !v.name) { > reply_with_perror ("allocate"); > free (ret->guestfs_int_dirent_list_val); > + free (p); > + free (v.name); > free (ret); > closedir (dir); > return NULL; > -- > 1.6.3.3.507.gc6b5a +1 -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Fri Jul 3 14:38:37 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:38:37 +0100 Subject: [fedora-virt] [PATCH libguestfs] remove trailing blanks In-Reply-To: <87ab3lq5bg.fsf@meyering.net> References: <87ab3lq5bg.fsf@meyering.net> Message-ID: <20090703143837.GE30950@amd.home.annexia.org> On Fri, Jul 03, 2009 at 03:11:47PM +0200, Jim Meyering wrote: > Hi Rich, > > What do you think about this? > I was slightly annoyed to see occasional trailing blanks > being highlighted. This removes them all: I was a bit surprised that there were trailing blanks, since I'm usual careful to avoid them. So +1. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From rjones at redhat.com Fri Jul 3 14:39:11 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:39:11 +0100 Subject: [fedora-virt] [PATCH libguestfs] avoid leak upon failed realloc In-Reply-To: <874ottq59q.fsf@meyering.net> References: <874ottq59q.fsf@meyering.net> Message-ID: <20090703143911.GA3841@amd.home.annexia.org> On Fri, Jul 03, 2009 at 03:12:49PM +0200, Jim Meyering wrote: > Hi again, > > No big deal, but might as well fix this... Yup, +1. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Fri Jul 3 14:40:25 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 15:40:25 +0100 Subject: [fedora-virt] [PATCH libguestfs] generate slightly more "const-correct" code In-Reply-To: <87y6r5oqae.fsf@meyering.net> References: <87y6r5oqae.fsf@meyering.net> Message-ID: <20090703144025.GA3856@amd.home.annexia.org> On Fri, Jul 03, 2009 at 03:21:45PM +0200, Jim Meyering wrote: > const correctness is nice. > These changes exposed no problems and induced no new warnings. Yes, all looks good. +1. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From markmc at redhat.com Fri Jul 3 15:49:14 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 03 Jul 2009 16:49:14 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1246628572.13604.2.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> Message-ID: <1246636154.13604.8.camel@blaa> And now showing to a select preview audience: == libvirt == * Fri Jul 3 2009 Daniel Veillard - 0.6.5-1.fc12 - Upstream release of 0.6.5 - OpenNebula driver - many bug fixes Cheers, Mark. From markmc at redhat.com Fri Jul 3 15:52:57 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 03 Jul 2009 16:52:57 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> Message-ID: <1246636377.13604.10.camel@blaa> Hi Jerry, On Mon, 2009-06-29 at 11:38 -0600, Jerry James wrote: > > I'm having a problem with a virtual machine created on an F-11 host > that I didn't have with an F-10 host, and I'm wondering if I've > misconfigured something or missed a trick somewhere. I'm doing some > custom Linux kernel work for my employer, and I'm using a small > collection of virtual machines to test it. In the short time I've had > F-11 on my host machine, I've seen that virtual disk performance is > noticeably worse than it was with F-10. I'm not sure if you noticed in the other thread, but from: https://bugzilla.redhat.com/509383 Does running: for f in /sys/block/vd*/queue/rotational; do echo 1 > $f; done inside the guest help? Cheers, Mark. From markmc at redhat.com Fri Jul 3 15:59:59 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 03 Jul 2009 16:59:59 +0100 Subject: [fedora-virt] F-11 libvirt no longer creating firewall/iptables rules for virtual network? In-Reply-To: <645d17210906251143p4f05eb95s477e1382273e9b57@mail.gmail.com> References: <645d17210906251143p4f05eb95s477e1382273e9b57@mail.gmail.com> Message-ID: <1246636799.13604.11.camel@blaa> Hi Jonathan, On Thu, 2009-06-25 at 19:43 +0100, Jonathan Underwood wrote: > Hi there, > > I've recently installed F-11 and am having a problem with networking > between the host and guest with the default network configuration - > specifically that the iptables rules for virbr0 are not being inserted > by libvirt as they used to be under F-10. > > I am using the default configuration of the firewall as shipped with > F-11. The guest instance is a windowsXP image created under F-10 - I > simply recreated the cconfig files by "creating" a new guest under > virt-manager and pointing it to the disk image file. The guest boots > up fine, but no networking. The output of iptables -L doesn't contain > any reference to virbr0 or vnet0 (the latter automatically created > when starting the guest OS) - I have confirmed virbr0 and vnet0 are > present using ifconfig.. In case it's relevant this machine is using > NetworkManager and has a single wired ethernet adapter configured with > a static IP. > > Any suggestions on how I can debug further ? Did you figure out what the issue here was? Thanks, Mark. From jonathan.underwood at gmail.com Fri Jul 3 16:29:56 2009 From: jonathan.underwood at gmail.com (Jonathan Underwood) Date: Fri, 3 Jul 2009 17:29:56 +0100 Subject: [fedora-virt] F-11 libvirt no longer creating firewall/iptables rules for virtual network? In-Reply-To: <1246636799.13604.11.camel@blaa> References: <645d17210906251143p4f05eb95s477e1382273e9b57@mail.gmail.com> <1246636799.13604.11.camel@blaa> Message-ID: <645d17210907030929u470adbf2yfe2b9f5f2766fdea@mail.gmail.com> Hi Mark, 2009/7/3 Mark McLoughlin : > Did you figure out what the issue here was? I am afraid I didn't get to the bottom of the problem because updated packages for F-11 libvirt appeared which I installed, and they fixed the problem. My observation was that with previous packages that a "service libvirtd [reload|restart]" wasn't recreating the needed iptables rules though. If it's useful I could dig deeper and try reinstalling the old packages and try to recreate the problem, but I'm not sure it's worth the trouble. J. From markmc at redhat.com Fri Jul 3 16:30:07 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 03 Jul 2009 17:30:07 +0100 Subject: [fedora-virt] Fedora virt status Message-ID: <1246638607.13604.13.camel@blaa> F-12 ==== F-12 is still coming at us fast: http://fedoraproject.org/wiki/Releases/12/Schedule 2009-07-28 Feature Freeze (26 days) 2009-09-22 Beta (Final Development) Free (82 days) 2009-10-20 Final Release Compose (110 days) libguestfs ========== Much libguestfs activity has continued on fedora-virt at redhat.com lately and Rich Jones has posted two related F-12 feature pages: https://fedoraproject.org/wiki/Features/libguestfs https://fedoraproject.org/wiki/Features/Xen_to_KVM_migration FWN === Yet another weekly installment from Dale Bewley: https://fedoraproject.org/wiki/FWN/Issue182#Virtualization libvirt-0.6.5 ============= The libvirt folks have released another version of libvirt: http://www.redhat.com/archives/libvir-list/2009-July/msg00060.html This is mostly a bug fix release, though it includes some serious improvements for storage/NPIV and on the OpenNebula driver: * New features - create storage columes on disk backend (Henrik Persson) - drop of capabilities based on libcap-ng when possible (Daniel Berrange) qemu-fedora.git =============== git is now being used to manage Fedora's qemu patches: http://www.redhat.com/archives/fedora-virt/2009-June/msg00157.html Glauber and I are going to start using git to manage the patches for the qemu package. The idea is that we'll use git's magical powers to make it easier for us to fix problems in patches, cherry-pick patches from upstream, re-base our patches to a newer upstream, etc. http://git.et.redhat.com/?p=qemu-fedora.git Already, this has proved useful re-basing to the latest qemu-kvm-0.10.50 snapshot (kvm-87). F-11 virtio-blk Performance =========================== Charles Duffy, Michael Tokarev, Rich Jones and others recently stumbled across the apparent cause of a dramatic slowdown in virtio-blk performance in F-11 guests: https://bugzilla.redhat.com/509383 Thanks for Michael Tokarev and Charles Duffy for the following suggestion which has mostly fixed this problem: for f in /sys/block/vd*/queue/rotational; do echo 1 > $f; done It seems the kernel folks deemed it prudent to turn KVM and Xen paravirt disks into "non-rotational" disks in 2.6.29, thereby preventing guests from attempting to optimize block I/O and, instead, leaving it up to the host: http://lkml.org/lkml/2008/10/27/84 No doubt there'll be more on this as people look deeper into the issue. KVM USB Passthrough =================== A discussion at FUDCon lead to some tips on USB passthrough being posted to the fedora-virt list: http://www.redhat.com/archives/fedora-virt/2009-June/msg00182.html "KVM, enabling iPhone-touting geeks everywhere to use iTunes" :-) Wiki ==== Dan Berrange has pulled together a couple of new wiki pages which people might find interesting. The first outlines the history of virt in Fedora, with details of what changes were made in each release: https://fedoraproject.org/wiki/Virtualization/History The second pulls together links to all the virt status reports and FWN virt sections: https://fedoraproject.org/wiki/Virtualization/News Xen === Michael Young posted more Dom0 kernel builds here: http://www.redhat.com/archives/fedora-virt/2009-June/msg00205.html Michael also pointed out Jeremy Fitzhardinge's latest prognosis of getting the dom0 patches merged upstream: http://lists.xensource.com/archives/html/xen-devel/2009-06/msg01193.html For now I've backed off putting anything much into the current merge window, or even the next, in favour of getting the tree into good shape for Xen users and working out what needs to happen to get a solid set of upstreamable patches. Bugs ==== DOOM-O-METER: 242 open bugs a couple of weeks ago, 250 now = New = == kvm == https://bugzilla.redhat.com/508801 kvm "emulation failed (pagetable)" during OpenBSD 4.6-beta guest boot (OOS shadow bug?) It looks like this OpenBSD guest boot failure on F-11 might be due to an OOS shadow bug but, then again, that should have been fixed in 2.6.29.3. https://bugzilla.redhat.com/509383 mkfs.ext2 much slower with virtio-backed disks than with IDE-backed disks (NOT sparseness issue) The problem here seems to be that virtio_blk is now defaulting to non-rotational mode since 2.6.29. This may also be the cause of bug #505695 and bug #504376. == qemu == https://bugzilla.redhat.com/507899 qemu's console-via-VNC generates invalid rect position(s) qemu's VNC server sends bogus rectangle sizes causing vncviewer to abort. https://bugzilla.redhat.com/507834 Clock drift in RHEL5.3 KVM Guests on Heavily Loaded Servers A report of x86_64 RHEL5 guests time drifting under KVM with the jiffies clocksource. Suggestion to boot with "notsc divider=10". Macelo also suggests "clock=tsc" or "clock=jiffies" with -no-kvm-pit-reinjection. https://bugzilla.redhat.com/508258 qemu init script does nothing useful by default The qemu initscript for registering binary handlers for the usermode emulators does nothing unless you obtain the runtime environment for the emulator from somewhere else. This is lame. https://bugzilla.redhat.com/509532 Move /usr/bin/qemu-kvm into the qemu-kvm package A minor packaging change we should make for F-12. == libvirt == https://bugzilla.redhat.com/508645 libvirt should use qemu's autoconnect mode for USB device passthrough qemu has a nice autoconnect mode for USB passthrough which libvirt should probably use by default. Dan suggests that it should only be used with managed='yes'. https://bugzilla.redhat.com/508317 Allow sound devices to be used with svirt - tunnel sound over VNC Covers the fact that with svirt we now disable sound cards until we can tunnel sound over VNC. https://bugzilla.redhat.com/509458 libvirtd default virtual network should not be enabled when libvirt installed in a guest This issue has been known for a while now - if you install libvirtd in a guest, the default network is enabled and since it's using the same IP range as the default network in the host, things get screwed up. Suggestions on how to avoid having libvirtd or the default network enabled by default in guest installs welcome :-) == virt-manager= https://bugzilla.redhat.com/508665 virt-manager (running as unprivileged user) doesn't let me install from NFS locations Because virt-manager no longer runs as root, NFS installs don't work. Suggestion is that we'll use PolicyKit to allow virt-manager to do NFS mounts. == virt-top == https://bugzilla.redhat.com/508197 virt-top segfaults if run in Japanese Now there's a bug that's right up Rich's alley! = Resolved = == qemu == https://bugzilla.redhat.com/508326 Force use of /sys/bus/usb for all USB host devices qemu is currently prefering to use usbfs instead of sysfs for USB passthrough. Fix sent upstream and built in rawhide. https://bugzilla.redhat.com/506170 removing virtualization packages leaves qemu-system-x86 This is NOTABUG - if 'yum groupinstall' pulls in packages via dependencies, then 'yum groupremove' doesn't remove them again. == libvirt == https://bugzilla.redhat.com/506590 libvirt should ignore NUMA cells with missing topology The libvirt fix for this was committed upstream but a recent F-11 numactl update is enough to fix the original issue for the reported, so this has been marked as fixed upstream. https://bugzilla.redhat.com/507555 libvirt starting a guest with ISO on NFS mount fails when unnecessarily setting SELinux file context Patch from Tim Waugh sent upstream and included in libvirt-0.6.2-13.fc11 F-11 update. https://bugzilla.redhat.com/505625 libvirtd segfault during virsh dominfo on security model This libvirtd segfault which occurs when you do "virsh capabilities" followed by "virsh dominfo" is fix in the libvirt-0.6.2-13.fc11 F-11 update. https://bugzilla.redhat.com/493692 Creating new VM; SELinux prevents opening iso image of install media https://bugzilla.redhat.com/499569 Guest with source-less cdrom fails to start :: Failed to set security label Two patches which we included in F-11, but neglected to send upstream and were then dropped accidentally when we rebased to 0.6.4. All sorted out again now for F-12. == virt-viewer == https://bugzilla.redhat.com/508825 virt-viewer doesnt have "full screen" hot key It seems sensible that we would hook up F11 for fullscreen and have virt-manager handle it, rather than passing F11 through to the guest. Dan thinks this is a dumb idea, so the bug is closed as WONTFIX. From lfarkas at lfarkas.org Fri Jul 3 17:03:51 2009 From: lfarkas at lfarkas.org (Farkas Levente) Date: Fri, 03 Jul 2009 19:03:51 +0200 Subject: [fedora-virt] Fedora virt status In-Reply-To: <1246638607.13604.13.camel@blaa> References: <1246638607.13604.13.camel@blaa> Message-ID: <4A4E39F7.8050807@lfarkas.org> Mark McLoughlin wrote: > qemu-fedora.git > =============== > > git is now being used to manage Fedora's qemu patches: > > http://www.redhat.com/archives/fedora-virt/2009-June/msg00157.html > > Glauber and I are going to start using git to manage the patches for > the qemu package. The idea is that we'll use git's magical powers to > make it easier for us to fix problems in patches, cherry-pick patches > from upstream, re-base our patches to a newer upstream, etc. > > http://git.et.redhat.com/?p=qemu-fedora.git > > Already, this has proved useful re-basing to the latest > qemu-kvm-0.10.50 snapshot (kvm-87). wouldn't be it too much? there is an upstream qemu git, there is a qemu-kvm git (which is also a redhat project) now fedora fork a fork!? -- Levente "Si vis pacem para bellum!" From ehabkost at redhat.com Fri Jul 3 17:38:30 2009 From: ehabkost at redhat.com (Eduardo Habkost) Date: Fri, 3 Jul 2009 14:38:30 -0300 Subject: [fedora-virt] Fedora virt status In-Reply-To: <4A4E39F7.8050807@lfarkas.org> References: <1246638607.13604.13.camel@blaa> <4A4E39F7.8050807@lfarkas.org> Message-ID: <20090703173830.GA9711@blackpad> On Fri, Jul 03, 2009 at 07:03:51PM +0200, Farkas Levente wrote: > Mark McLoughlin wrote: > > qemu-fedora.git > > =============== > > > > git is now being used to manage Fedora's qemu patches: > > > > http://www.redhat.com/archives/fedora-virt/2009-June/msg00157.html > > > > Glauber and I are going to start using git to manage the patches for > > the qemu package. The idea is that we'll use git's magical powers to > > make it easier for us to fix problems in patches, cherry-pick patches > > from upstream, re-base our patches to a newer upstream, etc. > > > > http://git.et.redhat.com/?p=qemu-fedora.git > > > > Already, this has proved useful re-basing to the latest > > qemu-kvm-0.10.50 snapshot (kvm-87). > > wouldn't be it too much? there is an upstream qemu git, there is a > qemu-kvm git (which is also a redhat project) now fedora fork a fork!? This is just storing the (five) patches that already exist on the Fedora package (that are all supposed to be submitted upstream) in a git repository, to help manage them, not the creation of a fork. -- Eduardo From rjones at redhat.com Fri Jul 3 18:20:41 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 3 Jul 2009 19:20:41 +0100 Subject: [fedora-virt] Fedora virt status In-Reply-To: <1246638607.13604.13.camel@blaa> References: <1246638607.13604.13.camel@blaa> Message-ID: <20090703182041.GA5052@amd.home.annexia.org> On Fri, Jul 03, 2009 at 05:30:07PM +0100, Mark McLoughlin wrote: > libguestfs > ========== > > Much libguestfs activity has continued on fedora-virt at redhat.com I also just requested a new mailing list for libguestfs, so that development discussions and patches and so on won't disturb people asking Fedora virt questions. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From loganjerry at gmail.com Fri Jul 3 18:31:14 2009 From: loganjerry at gmail.com (Jerry James) Date: Fri, 3 Jul 2009 12:31:14 -0600 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <1246636377.13604.10.camel@blaa> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <1246636377.13604.10.camel@blaa> Message-ID: <870180fe0907031131x3c9bfbd8wc31d0bfdc212d6e8@mail.gmail.com> On Fri, Jul 3, 2009 at 9:52 AM, Mark McLoughlin wrote: > I'm not sure if you noticed in the other thread, but from: > > ?https://bugzilla.redhat.com/509383 > > Does running: > > ?for f in /sys/block/vd*/queue/rotational; do echo 1 > $f; done > > inside the guest help? I saw that. However, the guest where I'm having the problem doesn't have a file named "rotational" in the "queue" directory. It's running kernel version 2.6.28.9. In what version did "rotational" appear? I made a Rawhide guest a few days ago, but it is currently only slightly usable (gdm appears to be having some problems). I'll try this once that guest is a little more usable. Thanks, -- Jerry James http://www.jamezone.org/ From agx at sigxcpu.org Sat Jul 4 17:08:42 2009 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Sat, 4 Jul 2009 19:08:42 +0200 Subject: [fedora-virt] Updated libguestfs Debian packages Message-ID: <20090704170842.GA4012@bogon.sigxcpu.org> Hi, I've uploaded a new versions of the libguestfs Debian packages to alioth. Please see: http://wiki.debian.org/Teams/DebianLibvirtTeam#Packages for download instructions. Changes are: * ship virt-inspect in the guestfish package * speedup appliance startup by almost a factor of two * fix augeas support in the appliance (which I broke previously) * allow to build on amd64 Many thanks to Richard for applying the patches upstream so quickly! Cheers, -- Guido From gene at czarc.net Sat Jul 4 17:54:20 2009 From: gene at czarc.net (Gene Czarcinski) Date: Sat, 4 Jul 2009 13:54:20 -0400 Subject: [fedora-virt] vmware guest -> Fedora-virt guest Message-ID: <200907041354.20505.gene@czarc.net> Does anyone know if it is possible to "convert" a VMware guest to be a Fedora- virtualization guest? I first tried with Win2k. I know that Win2k basically works becasue I did a fresh install onto a virtual IDE disk. But, my Vmware guest uses a SCSI disk. Could not get it to work. OK, so lets try something simpler: Fedora 9. Rather than going the whole way, lets just see if I can get the disk to be recognized. So, define a new guest with a IDE virtual disk and a Fedora 9 install disk ISO image. Boot up into rescue mode. 1. First, add a new storage SCSI device and use the vmdk file from VMware ... nope, no good partition table. 2. Next, convert the vmdk file to raw using qemu-img and use this raw image for a new storage SCSI device ... still did not work ... no good partition table (fdisk -l). What am I doing wrong? Does anyone know if the SCSI device support works? GEne From rjones at redhat.com Sat Jul 4 22:40:04 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sat, 4 Jul 2009 23:40:04 +0100 Subject: [fedora-virt] vmware guest -> Fedora-virt guest In-Reply-To: <200907041354.20505.gene@czarc.net> References: <200907041354.20505.gene@czarc.net> Message-ID: <20090704224004.GA10269@amd.home.annexia.org> On Sat, Jul 04, 2009 at 01:54:20PM -0400, Gene Czarcinski wrote: > 2. Next, convert the vmdk file to raw using qemu-img and use this raw image for > a new storage SCSI device ... still did not work ... no good partition table > (fdisk -l). Using qemu-img to convert the vmdk images to raw should work. Once a vmx file has been unpacked, it often[1] contains several individual *.vmdk files which you have to convert and reassemble into a raw file. Use a command like: qemu-img convert -f vmdk -O raw image-s0*.vmdk image.raw The question is, why do you get no partition table. You can try to examine the image in guestfish[2] to see what exactly it contains - eg. does it have a good partition table, does it have any LVM LVs, etc: $ guestfish -a image.raw --ro > run > list-devices > list-partitions > lvs You can also use virt-inspector to see what kernel / drivers are installed. Rich. [1] I wonder if these are snapshots. [2] http://koji.fedoraproject.org/koji/packageinfo?packageID=8391 -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From markmc at redhat.com Mon Jul 6 07:28:02 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Mon, 06 Jul 2009 08:28:02 +0100 Subject: [fedora-virt] Disk device performance in F11 In-Reply-To: <870180fe0907031131x3c9bfbd8wc31d0bfdc212d6e8@mail.gmail.com> References: <870180fe0906291038x1fa01051ude4f6ca477c82fe8@mail.gmail.com> <1246636377.13604.10.camel@blaa> <870180fe0907031131x3c9bfbd8wc31d0bfdc212d6e8@mail.gmail.com> Message-ID: <1246865282.5451.24.camel@blaa> On Fri, 2009-07-03 at 12:31 -0600, Jerry James wrote: > On Fri, Jul 3, 2009 at 9:52 AM, Mark McLoughlin wrote: > > I'm not sure if you noticed in the other thread, but from: > > > > https://bugzilla.redhat.com/509383 > > > > Does running: > > > > for f in /sys/block/vd*/queue/rotational; do echo 1 > $f; done > > > > inside the guest help? > > I saw that. However, the guest where I'm having the problem doesn't > have a file named "rotational" in the "queue" directory. It's running > kernel version 2.6.28.9. In what version did "rotational" appear? Ah, okay - this file was only added in 2.6.29, and in 2.6.28 virtio-blk used rotational mode anyway. Cheers, Mark. From markmc at redhat.com Mon Jul 6 08:11:09 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Mon, 06 Jul 2009 09:11:09 +0100 Subject: [fedora-virt] vmware guest -> Fedora-virt guest In-Reply-To: <200907041354.20505.gene@czarc.net> References: <200907041354.20505.gene@czarc.net> Message-ID: <1246867869.5451.42.camel@blaa> On Sat, 2009-07-04 at 13:54 -0400, Gene Czarcinski wrote: > Does anyone know if it is possible to "convert" a VMware guest to be a > Fedora-virtualization guest? Have you tried the virt-convert tool from the python-virtinst package? Cheers, Mark. From gene at czarc.net Mon Jul 6 12:57:15 2009 From: gene at czarc.net (Gene Czarcinski) Date: Mon, 6 Jul 2009 08:57:15 -0400 Subject: [fedora-virt] vmware guest -> Fedora-virt guest In-Reply-To: <20090704224004.GA10269@amd.home.annexia.org> References: <200907041354.20505.gene@czarc.net> <20090704224004.GA10269@amd.home.annexia.org> Message-ID: <200907060857.16481.gene@czarc.net> On Saturday 04 July 2009 18:40:04 Richard W.M. Jones wrote: > On Sat, Jul 04, 2009 at 01:54:20PM -0400, Gene Czarcinski wrote: > > 2. Next, convert the vmdk file to raw using qemu-img and use this raw > > image for a new storage SCSI device ... still did not work ... no good > > partition table (fdisk -l). > > Using qemu-img to convert the vmdk images to raw should work. Once a > vmx file has been unpacked, it often[1] contains several individual > *.vmdk files which you have to convert and reassemble into a raw file. > Use a command like: > > qemu-img convert -f vmdk -O raw image-s0*.vmdk image.raw > > The question is, why do you get no partition table. You can try to > examine the image in guestfish[2] to see what exactly it contains - > eg. does it have a good partition table, does it have any LVM LVs, > etc: > > $ guestfish -a image.raw --ro > > > run > > list-devices > > list-partitions > > lvs > > You can also use virt-inspector to see what kernel / drivers are > installed. > > Rich. > > [1] I wonder if these are snapshots. > > [2] http://koji.fedoraproject.org/koji/packageinfo?packageID=8391 First of all, let me thank you for the tip on guestfish. I am a newbie to Fedora-virtualization and am not aware of all the packages involves let alone all of the functions/packages that could be useful. It would be nice if there was a list somewhere which listed such packages along with a brief description of what each did. The vmware virtual disk file I used was first made into a single file rahter than split using vmware-vdiskmager. OK, I used guestfish to verify that my "raw" image of a virtual disk was good. I then realized that part of my problem was that the rescue-mode system on the Fedora 9 netinst and the one on the Fedora 11 netinst differed in the order of disks (what was sda and what was sdb). Once I figured that out, things looked better. I deleted the ide disk definition so that only the sda scsi virtual disk pointing at my converted file was defined. I tried booting up ... the kernel boots but then cannot find anything. Well, this guest uses LVM for swap and "/". lets, try something simpler. I next built a small (minimal install) Fedora 9 vmware guest with sda1, sda2, and sda3 as /boot, swap, and "/" respectively.. I took the vmdk file and converted it to raw. OK, plug this file into Fedora-virtualization as sda. First, boot up with the Fedora 9 netinst ISO image and I am able to "chroot /mnt/sysimage" to the system ... looks great. Try booking ... kernel; loads but fails because it cannot find anything such as "/dev/root", "/sys", or /selinux". Any suggestions? Gene From pasik at iki.fi Mon Jul 6 14:32:50 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Mon, 6 Jul 2009 17:32:50 +0300 Subject: [fedora-virt] Fedora XenPvopsDom0 wiki page updated Message-ID: <20090706143250.GC24960@edu.joroinen.fi> Hello. I just updated Fedora XenPvopsDom0 wiki page: https://fedoraproject.org/wiki/Features/XenPvopsDom0 I added a link to pv_ops dom0 kernel testing RPMs by M A Young, link to upstream XenDom0Kernels wiki page and also a link to recent pv_ops dom0 status email. -- Pasi From rjones at redhat.com Tue Jul 7 15:26:25 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 7 Jul 2009 16:26:25 +0100 Subject: [fedora-virt] Re: febootstrap question In-Reply-To: <63aeb0300907070758x1d9a1899y23067c006d33b4b5@mail.gmail.com> References: <63aeb0300906171425l3da1156aydc9b7a649e4ce00d@mail.gmail.com> <20090617213802.GA3309@amd.home.annexia.org> <63aeb0300906191444r353d2242x6bf3385e728f177c@mail.gmail.com> <20090619225723.GB15252@amd.home.annexia.org> <63aeb0300907070758x1d9a1899y23067c006d33b4b5@mail.gmail.com> Message-ID: <20090707152625.GN25296@amd.home.annexia.org> On Tue, Jul 07, 2009 at 10:58:32AM -0400, Christopher Johnston wrote: > Wanted to updated you on what I was working on using febootstrap. I managed > to get a fully booted F10 system that can be PXE booted and pivot the rootfs > filesystem into tmpfs. It then forks init off to start the usual boot > process. Very happy so far with how it is coming along with the project. > The source of the problem turned out to be the upx binary minimize process, > once I disabled that it worked great. Yes I should probably just remove upx support, since it's nothing but trouble and saves very little space. > I am running into another smaller issue where the rpmdb gets corrupted after > the system boots. I am also not running the minimizer to remove the rpmdb > as I need this at boot time when the system is up and running to install > some required RPMs. For febootstrap, remember that you are using the host yum/rpm to initially create the initramfs. When you later boot the system you're using the installed yum/rpm, which could well be different versions. (Same thing happens with mock BTW). > Here is the chroot environment for the image, strangely rpm -qa doesnt > report anything yet the files are all in tack (strings Packages even shows > data). Have you seen this where the rpmdb gets corrupted at boot time? > > > CHROOT: > [root at ns4 /]# cd /var/lib/rpm/ > [root at ns4 rpm]# ls > Basenames Dirnames Group Name Providename Pubkeys > Requireversion Sigmd5 __db.000 __db.002 __db.004 > Conflictname Filedigests Installtid Packages Provideversion Requirename > Sha1header Triggername __db.001 __db.003 > [root at ns4 rpm]# rm -f __db.00* Is this running using 'febootstrap-run' or using a plain fakechroot or are you really running this as root? Using 'rm' directly on files in the chroot is usually a bad idea. See the discussion here: http://git.et.redhat.com/?p=febootstrap.git;a=blob;f=febootstrap.pod;h=e208603bc9fd670857df1b7419fffd1d2986c024;hb=HEAD#l108 > [root at ns4 rpm]# rpm --rebuilddb Similarly, it's only safe to use 'febootstrap-run' to run commands. Or run the commands only in a booted system. [...] > BOOTED SYSTEM: > > [root at core021 yum.repos.d]# rpm -qa > rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9 > error: cannot open Packages index using db3 - Invalid argument (22) > error: cannot open Packages database in /var/lib/rpm > rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9 > error: cannot open Packages database in /var/lib/rpm See above on difference between host and installed RPM. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From rjones at redhat.com Tue Jul 7 15:34:54 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 7 Jul 2009 16:34:54 +0100 Subject: [fedora-virt] Re: febootstrap question In-Reply-To: <20090707152625.GN25296@amd.home.annexia.org> References: <63aeb0300906171425l3da1156aydc9b7a649e4ce00d@mail.gmail.com> <20090617213802.GA3309@amd.home.annexia.org> <63aeb0300906191444r353d2242x6bf3385e728f177c@mail.gmail.com> <20090619225723.GB15252@amd.home.annexia.org> <63aeb0300907070758x1d9a1899y23067c006d33b4b5@mail.gmail.com> <20090707152625.GN25296@amd.home.annexia.org> Message-ID: <20090707153454.GA4017@amd.home.annexia.org> On Tue, Jul 07, 2009 at 04:26:25PM +0100, Richard W.M. Jones wrote: > Using 'rm' directly on files in the chroot is usually a bad idea. See > the discussion here: > > http://git.et.redhat.com/?p=febootstrap.git;a=blob;f=febootstrap.pod;h=e208603bc9fd670857df1b7419fffd1d2986c024;hb=HEAD#l108 > > > [root at ns4 rpm]# rpm --rebuilddb > > Similarly, it's only safe to use 'febootstrap-run' to run commands. You might also want to consider the hoops that libguestfs goes through so it only runs commands safely: http://git.et.redhat.com/?p=libguestfs.git;a=blob;f=appliance/make.sh.in;hb=HEAD Every time we run a command on the initramfs, it's wrapped in a call to febootstrap-run or febootstrap-install (the latter to install extra files). If you don't do that you can end up with a corrupted/mismatching fakeroot.log which causes all sorts of subtle and unpredictable problems. eg. We had one where "find" would segfault at random times, and we traced it back to a single use where we had copied a file into the fakeroot without using febootstrap-install. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rvandolson at esri.com Tue Jul 7 18:09:13 2009 From: rvandolson at esri.com (Ray Van Dolson) Date: Tue, 7 Jul 2009 11:09:13 -0700 Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x Message-ID: <20090707180913.GA7411@esri.com> Hi all; Trying to deploy a CentOS 5 domU under RHEL 5.3 64-bit and am running into the following error: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') Domain installation may not have been successful. If it was, you can restart your domain by running 'virsh start cobbler'; otherwise, please restart your installation. Tue, 07 Jul 2009 10:59:38 ERROR virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') Traceback (most recent call last): File "/usr/sbin/virt-install", line 560, in ? main() File "/usr/sbin/virt-install", line 492, in main dom = guest.start_install(conscb, progresscb, wait=(not wait)) File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 822, in start_install return self._do_install(consolecb, meter, wait) File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 843, in _do_install self.domain = self.conn.createLinux(install_xml, 0) File "/usr/lib64/python2.4/site-packages/libvirt.py", line 573, in createLinux if ret is None:raise libvirtError('virDomainCreateLinux() failed', conn=self) libvirtError: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') This only seems to happen when I pass my virt-install command as follows: virt-install --name cobbler --ram 1024 --file=/ludlow2/cobbler.img \ --vnc --vcpus=2 --nonsparse -w bridge:xenbr0 -l \ http://yummie.esri.com/mrepo/centos5-x86_64/os/ \ -x "updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2" \ --os-type=linux -d The error appears to be triggered by my kickstart URL location which includes ampersands and such -- despite the fact that I am include quotes around the entire argument. The debug output indicates that the XML is being written with the ampersand changed into &. If I change my kickstart location to a URL without the GET variables, everything works fine. Bug? Expected behavior? Workaround? Perhaps this is an issue in virt-install and wouldn't happen if I crafted the XML file myself? python-virtinst-0.300.2-12.el5 Thanks, Ray From james.mcevoy at hp.com Tue Jul 7 18:43:34 2009 From: james.mcevoy at hp.com (McEvoy, James) Date: Tue, 7 Jul 2009 18:43:34 +0000 Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x In-Reply-To: <20090707180913.GA7411@esri.com> References: <20090707180913.GA7411@esri.com> Message-ID: <197A4D1DF629F64A9260E3B454A218D13403CBF2D3@GVW1158EXB.americas.hpqcorp.net> Try single quotes or use back slashes to escape the ampersands --jim -----Original Message----- From: fedora-virt-bounces at redhat.com [mailto:fedora-virt-bounces at redhat.com] On Behalf Of Ray Van Dolson Sent: Tuesday, July 07, 2009 11:09 AM To: fedora-virt at redhat.com Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x Hi all; Trying to deploy a CentOS 5 domU under RHEL 5.3 64-bit and am running into the following error: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') Domain installation may not have been successful. If it was, you can restart your domain by running 'virsh start cobbler'; otherwise, please restart your installation. Tue, 07 Jul 2009 10:59:38 ERROR virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') Traceback (most recent call last): File "/usr/sbin/virt-install", line 560, in ? main() File "/usr/sbin/virt-install", line 492, in main dom = guest.start_install(conscb, progresscb, wait=(not wait)) File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 822, in start_install return self._do_install(consolecb, meter, wait) File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 843, in _do_install self.domain = self.conn.createLinux(install_xml, 0) File "/usr/lib64/python2.4/site-packages/libvirt.py", line 573, in createLinux if ret is None:raise libvirtError('virDomainCreateLinux() failed', conn=self) libvirtError: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') This only seems to happen when I pass my virt-install command as follows: virt-install --name cobbler --ram 1024 --file=/ludlow2/cobbler.img \ --vnc --vcpus=2 --nonsparse -w bridge:xenbr0 -l \ http://yummie.esri.com/mrepo/centos5-x86_64/os/ \ -x "updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2" \ --os-type=linux -d The error appears to be triggered by my kickstart URL location which includes ampersands and such -- despite the fact that I am include quotes around the entire argument. The debug output indicates that the XML is being written with the ampersand changed into &. If I change my kickstart location to a URL without the GET variables, everything works fine. Bug? Expected behavior? Workaround? Perhaps this is an issue in virt-install and wouldn't happen if I crafted the XML file myself? python-virtinst-0.300.2-12.el5 Thanks, Ray _______________________________________________ Fedora-virt mailing list Fedora-virt at redhat.com https://www.redhat.com/mailman/listinfo/fedora-virt From crobinso at redhat.com Tue Jul 7 18:52:41 2009 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 07 Jul 2009 14:52:41 -0400 Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x In-Reply-To: <20090707180913.GA7411@esri.com> References: <20090707180913.GA7411@esri.com> Message-ID: <4A539979.2050109@redhat.com> Ray Van Dolson wrote: > Hi all; > > Trying to deploy a CentOS 5 domU under RHEL 5.3 64-bit and am running > into the following error: > > virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > Domain installation may not have been > successful. If it was, you can restart your domain > by running 'virsh start cobbler'; otherwise, please > restart your installation. > Tue, 07 Jul 2009 10:59:38 ERROR virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > Traceback (most recent call last): > File "/usr/sbin/virt-install", line 560, in ? > main() > File "/usr/sbin/virt-install", line 492, in main > dom = guest.start_install(conscb, progresscb, wait=(not wait)) > File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 822, in start_install > return self._do_install(consolecb, meter, wait) > File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 843, in _do_install > self.domain = self.conn.createLinux(install_xml, 0) > File "/usr/lib64/python2.4/site-packages/libvirt.py", line 573, in createLinux > if ret is None:raise libvirtError('virDomainCreateLinux() failed', conn=self) > libvirtError: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > > This only seems to happen when I pass my virt-install command as > follows: > > virt-install --name cobbler --ram 1024 --file=/ludlow2/cobbler.img \ > --vnc --vcpus=2 --nonsparse -w bridge:xenbr0 -l \ > http://yummie.esri.com/mrepo/centos5-x86_64/os/ \ > -x "updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2" \ > --os-type=linux -d > > The error appears to be triggered by my kickstart URL location which > includes ampersands and such -- despite the fact that I am include > quotes around the entire argument. > > The debug output indicates that the XML is being written with the > ampersand changed into &. > > If I change my kickstart location to a URL without the GET variables, > everything works fine. > > Bug? Expected behavior? Workaround? Perhaps this is an issue in > virt-install and wouldn't happen if I crafted the XML file myself? > > python-virtinst-0.300.2-12.el5 > > Thanks, > Ray > Pretty sure we fixed bugs in this area in 5.3: run the command with --debug and see if the generated output has & in it. I think in this case it is actually xend that is choking, which I don't know any workaround for. - Cole From rvandolson at esri.com Tue Jul 7 18:58:07 2009 From: rvandolson at esri.com (Ray Van Dolson) Date: Tue, 7 Jul 2009 11:58:07 -0700 Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x In-Reply-To: <4A539979.2050109@redhat.com> References: <20090707180913.GA7411@esri.com> <4A539979.2050109@redhat.com> Message-ID: <20090707185807.GB8605@esri.com> On Tue, Jul 07, 2009 at 11:52:41AM -0700, Cole Robinson wrote: > Ray Van Dolson wrote: > > Hi all; > > > > Trying to deploy a CentOS 5 domU under RHEL 5.3 64-bit and am running > > into the following error: > > > > virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > > Domain installation may not have been > > successful. If it was, you can restart your domain > > by running 'virsh start cobbler'; otherwise, please > > restart your installation. > > Tue, 07 Jul 2009 10:59:38 ERROR virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > > Traceback (most recent call last): > > File "/usr/sbin/virt-install", line 560, in ? > > main() > > File "/usr/sbin/virt-install", line 492, in main > > dom = guest.start_install(conscb, progresscb, wait=(not wait)) > > File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 822, in start_install > > return self._do_install(consolecb, meter, wait) > > File "/usr/lib/python2.4/site-packages/virtinst/Guest.py", line 843, in _do_install > > self.domain = self.conn.createLinux(install_xml, 0) > > File "/usr/lib64/python2.4/site-packages/libvirt.py", line 573, in createLinux > > if ret is None:raise libvirtError('virDomainCreateLinux() failed', conn=self) > > libvirtError: virDomainCreateLinux() failed POST operation failed: (xend.err 'Invalid configuration unexpected EOF') > > > > This only seems to happen when I pass my virt-install command as > > follows: > > > > virt-install --name cobbler --ram 1024 --file=/ludlow2/cobbler.img \ > > --vnc --vcpus=2 --nonsparse -w bridge:xenbr0 -l \ > > http://yummie.esri.com/mrepo/centos5-x86_64/os/ \ > > -x "updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2" \ > > --os-type=linux -d > > > > The error appears to be triggered by my kickstart URL location which > > includes ampersands and such -- despite the fact that I am include > > quotes around the entire argument. > > > > The debug output indicates that the XML is being written with the > > ampersand changed into &. > > > > If I change my kickstart location to a URL without the GET variables, > > everything works fine. > > > > Bug? Expected behavior? Workaround? Perhaps this is an issue in > > virt-install and wouldn't happen if I crafted the XML file myself? > > > > python-virtinst-0.300.2-12.el5 > > > > Thanks, > > Ray > > > > Pretty sure we fixed bugs in this area in 5.3: run the command with > --debug and see if the generated output has & in it. Yep, did run with --debug (-d) and the XML output has & in it. I haven't yet tried the single quote option as a workaround however. Here is the cmdline generated (per debug output): updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2 method=http://yummie.esri.com/mrepo/centos5-x86_64/os/ > > I think in this case it is actually xend that is choking, which I don't > know any workaround for. > So xend should be able to handle & ? Or, if my had & instead of & would xend be able to handle that? I will try -- but curious if xend is supposed to work in either case. Thanks, Ray From crobinso at redhat.com Tue Jul 7 19:31:57 2009 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 07 Jul 2009 15:31:57 -0400 Subject: [fedora-virt] Invalid configuration unexpected EOF when using -x In-Reply-To: <20090707185807.GB8605@esri.com> References: <20090707180913.GA7411@esri.com> <4A539979.2050109@redhat.com> <20090707185807.GB8605@esri.com> Message-ID: <4A53A2AD.3060002@redhat.com> Ray Van Dolson wrote: > On Tue, Jul 07, 2009 at 11:52:41AM -0700, Cole Robinson wrote: >> Ray Van Dolson wrote: >>> virt-install --name cobbler --ram 1024 --file=/ludlow2/cobbler.img \ >>> --vnc --vcpus=2 --nonsparse -w bridge:xenbr0 -l \ >>> http://yummie.esri.com/mrepo/centos5-x86_64/os/ \ >>> -x "updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2" \ >>> --os-type=linux -d >>> >>> The error appears to be triggered by my kickstart URL location which >>> includes ampersands and such -- despite the fact that I am include >>> quotes around the entire argument. >>> >>> The debug output indicates that the XML is being written with the >>> ampersand changed into &. >>> >>> If I change my kickstart location to a URL without the GET variables, >>> everything works fine. >>> >>> Bug? Expected behavior? Workaround? Perhaps this is an issue in >>> virt-install and wouldn't happen if I crafted the XML file myself? >>> >>> python-virtinst-0.300.2-12.el5 >>> >>> Thanks, >>> Ray >>> >> Pretty sure we fixed bugs in this area in 5.3: run the command with >> --debug and see if the generated output has & in it. > > Yep, did run with --debug (-d) and the XML output has & in it. I > haven't yet tried the single quote option as a workaround however. > Argh, sorry, I didn't read your first message clearly. > Here is the cmdline generated (per debug output): > > updates=http://yummie.esri.com/updates/updates-el5.1.img ks=http://yummie/ks/ks.php?arch=x86_64&distro=centos&major=5&minor=2 method=http://yummie.esri.com/mrepo/centos5-x86_64/os/ > >> I think in this case it is actually xend that is choking, which I don't >> know any workaround for. >> > > So xend should be able to handle & ? Or, if my had & > instead of & would xend be able to handle that? > The & -> & replacement is necessary for XML, so it's only needed for talking to libvirt. That '&' should be getting converted back to plain & when passed off to xen. I think xen is just choking on the plain '&'. Try running the virtinst command with LIBVIRT_DEBUG=1 and see if there is a generated sexpr printed (like you get with xm list --long). - Cole From needwork at gmail.com Wed Jul 8 01:22:30 2009 From: needwork at gmail.com (Lester M.) Date: Wed, 8 Jul 2009 01:22:30 +0000 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? Message-ID: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> I downloaded the following rpms from M. Youngs fedora-people page. ( http://fedorapeople.org/~myoung/dom0/) kernel-firmware-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.noarch.rpm kernel-headers-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i586.rpm kernel-PAE-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm kernel-PAE-devel-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm I am interested in *Testing* under the understanding that this is in beta. My question is, after installation of the rpms, what configuration (config files, grub, et al) is needed to successfully boot into dom0? I recall there were a few hoops to jump through to get a working dom0. I also have compiled the xen3.4 tools (hg clone http://xenbits.xensource.com/xen-3.4-testing.hg) Could somebody please post a workflow for getting this running? I have installed the rpms and I am now like "Now what?" :-P -------------- next part -------------- An HTML attachment was scrubbed... URL: From pasik at iki.fi Wed Jul 8 10:32:30 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 13:32:30 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> Message-ID: <20090708103230.GS24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 01:22:30AM +0000, Lester M. wrote: > I downloaded the following rpms from M. Youngs fedora-people page. ( > http://fedorapeople.org/~myoung/dom0/) > > kernel-firmware-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.noarch.rpm > kernel-headers-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i586.rpm > kernel-PAE-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > kernel-PAE-devel-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > > I am interested in *Testing* under the understanding that this is in beta. > My question is, after installation of the rpms, what configuration (config > files, grub, et al) is needed to successfully boot into dom0? I recall there > were a few hoops to jump through to get a working dom0. > > I also have compiled the xen3.4 tools (hg clone > http://xenbits.xensource.com/xen-3.4-testing.hg) > You could also get the xen 3.4.0 hypervisor/tools RPMs from rawhide.. although from that xen-3.4-testing.hg repo you'll get 3.4.1-rc6 atm with a lot of fixes after 3.4.0. (I think the plan was to upload xen 3.4.1 to F11, later when it has been released upstream.) > Could somebody please post a workflow for getting this running? I have > installed the rpms and I am now like "Now what?" :-P Modify your grub.conf to boot the xen hypervisor, add line /etc/fstab to mount xenfs and hmm.. I guess that's it :) See: http://wiki.xensource.com/xenwiki/XenParavirtOps Pasting from that page: Working example grub.conf with VGA text console: title Xen 3.4-unstable, kernel 2.6.30-rc3-tip root (hd0,0) kernel /boot/xen-3.4-unstable.gz dom0_mem=512M module /boot/vmlinuz-2.6.30-rc3-tip root=/dev/sda1 ro module /boot/initrd.img-2.6.30-rc3-tip -- Pasi From needwork at gmail.com Wed Jul 8 14:05:55 2009 From: needwork at gmail.com (Lester M.) Date: Wed, 8 Jul 2009 10:05:55 -0400 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <20090708103230.GS24960@edu.joroinen.fi> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> Message-ID: <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> On Wed, Jul 8, 2009 at 6:32 AM, Pasi K?rkk?inen wrote: > On Wed, Jul 08, 2009 at 01:22:30AM +0000, Lester M. wrote: > > I downloaded the following rpms from M. Youngs fedora-people page. ( > > http://fedorapeople.org/~myoung/dom0/ > ) > > > > kernel-firmware-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.noarch.rpm > > kernel-headers-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i586.rpm > > kernel-PAE-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > > kernel-PAE-devel-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > > > > I am interested in *Testing* under the understanding that this is in > beta. > > My question is, after installation of the rpms, what configuration > (config > > files, grub, et al) is needed to successfully boot into dom0? I recall > there > > were a few hoops to jump through to get a working dom0. > > > > I also have compiled the xen3.4 tools (hg clone > > http://xenbits.xensource.com/xen-3.4-testing.hg) > > > > You could also get the xen 3.4.0 hypervisor/tools RPMs from rawhide.. > although from that xen-3.4-testing.hg repo you'll get 3.4.1-rc6 atm with a > lot of fixes after 3.4.0. > > (I think the plan was to upload xen 3.4.1 to F11, later when it has been > released > upstream.) > > > Could somebody please post a workflow for getting this running? I have > > installed the rpms and I am now like "Now what?" :-P > > Modify your grub.conf to boot the xen hypervisor, add line /etc/fstab to > mount xenfs and hmm.. I guess that's it :) > > See: http://wiki.xensource.com/xenwiki/XenParavirtOps > Pasting from that page: > > Working example grub.conf with VGA text console: > > title Xen 3.4-unstable, kernel 2.6.30-rc3-tip > root (hd0,0) > kernel /boot/xen-3.4-unstable.gz dom0_mem=512M > module /boot/vmlinuz-2.6.30-rc3-tip root=/dev/sda1 ro > module /boot/initrd.img-2.6.30-rc3-tip > > > -- Pasi > Thank you Pasi, Here is what my grub.conf entry looks like (with the xen-3.4.1 tools compiled,) after you install all 4 rpms from myoung's fedorapeople page: ( http://fedorapeople.org/~myoung/dom0/ ) title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root rhgb quiet nomodeset initrd /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img When you compile and install xen-3.4.1 the following is created in /boot: -rw-r--r--. 1 root root 498660 2009-07-07 17:08 xen-3.4.1-rc6.gz lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.4.gz -> xen-3.4.1-rc6.gz lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.gz -> xen-3.4.1-rc6.gz lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen.gz -> xen-3.4.1-rc6.gz I modified it per the pvops wiki page: ( http://wiki.xensource.com/xenwiki/XenParavirtOps) title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /xen-3.4.1-rc6.gz dom0_mem=512M module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root rhgb quiet module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img This is what is in my /etc/fstab: none /proc/xen xenfs defaults 0 0 So now I boot. When I boot the system the dom0 starts up instantly...., to the point where it says "scrubbing free ram" then the screen goes blank and all system activity ceases. Has anyone tried these rpms? I am not sure if i can scream out "bug!" "bug!" because I cannot find anyone that has actually installed these rpms as part of a deployment process, (a workflow, a howto, a "step by step" edit "this" or edit "that".) so I am not sure if it is that I am missing a config parameter or not. My hardware: Lenovo thinkpad T60 (Centrino Duo processor) ATI Radeon X1300 card (Its an "oldie" but on RHEL 5.3 it runs xen very very well.) -------------- next part -------------- An HTML attachment was scrubbed... URL: From pasik at iki.fi Wed Jul 8 14:45:53 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 17:45:53 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> Message-ID: <20090708144553.GW24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 10:05:55AM -0400, Lester M. wrote: > > Thank you Pasi, > > Here is what my grub.conf entry looks like (with the xen-3.4.1 tools > compiled,) after you install all 4 rpms from myoung's fedorapeople page: ( > http://fedorapeople.org/~myoung/dom0/ > ) > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > root (hd0,0) > kernel /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > root=/dev/mapper/vg01-lv_root rhgb quiet nomodeset > initrd /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > When you compile and install xen-3.4.1 the following is created in /boot: > > -rw-r--r--. 1 root root 498660 2009-07-07 17:08 xen-3.4.1-rc6.gz > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.4.gz -> > xen-3.4.1-rc6.gz > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.gz -> > xen-3.4.1-rc6.gz > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen.gz -> xen-3.4.1-rc6.gz > > > I modified it per the pvops wiki page: ( > http://wiki.xensource.com/xenwiki/XenParavirtOps) > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > root (hd0,0) > kernel /xen-3.4.1-rc6.gz dom0_mem=512M > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root rhgb quiet > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > This looks correct.. > > This is what is in my /etc/fstab: > > none /proc/xen xenfs defaults 0 0 > > > So now I boot. When I boot the system the dom0 starts up instantly...., to > the point where it says "scrubbing free ram" then the screen goes blank and > all system activity ceases. > Hmm.. try removing the "rhgb quiet" from the vmlinuz line in grub.conf. Is the last line you see something like this?: (XEN) Scrubbing Free RAM: ..........done. You could also try adding "loglvl=all guest_loglvl=all noreboot" to the xen.gz line to grub.conf. So try with this grub.conf: title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /xen-3.4.1-rc6.gz dom0_mem=512M loglvl=all guest_loglvl=all noreboot module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > Has anyone tried these rpms? I am not sure if i can scream out "bug!" "bug!" > because I cannot find anyone that has actually installed these rpms as part > of a deployment process, (a workflow, a howto, a "step by step" edit "this" > or edit "that".) so I am not sure if it is that I am missing a config > parameter or not. > I've used self-compiled pv_ops dom0 successfully on my testing box, but I haven't really tried this RPMs.. If you don't > My hardware: > > Lenovo thinkpad T60 (Centrino Duo processor) > ATI Radeon X1300 card > (Its an "oldie" but on RHEL 5.3 it runs xen very very well.) Laptop might be a tricky one.. but if RHEL 5.3 works on it, there's hope :) -- Pasi From pasik at iki.fi Wed Jul 8 14:49:25 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 17:49:25 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <20090708144553.GW24960@edu.joroinen.fi> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> Message-ID: <20090708144925.GX24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 05:45:53PM +0300, Pasi K?rkk?inen wrote: > On Wed, Jul 08, 2009 at 10:05:55AM -0400, Lester M. wrote: > > > > Thank you Pasi, > > > > Here is what my grub.conf entry looks like (with the xen-3.4.1 tools > > compiled,) after you install all 4 rpms from myoung's fedorapeople page: ( > > http://fedorapeople.org/~myoung/dom0/ > > ) > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > root (hd0,0) > > kernel /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > root=/dev/mapper/vg01-lv_root rhgb quiet nomodeset > > initrd /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > When you compile and install xen-3.4.1 the following is created in /boot: > > > > -rw-r--r--. 1 root root 498660 2009-07-07 17:08 xen-3.4.1-rc6.gz > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.4.gz -> > > xen-3.4.1-rc6.gz > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.gz -> > > xen-3.4.1-rc6.gz > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen.gz -> xen-3.4.1-rc6.gz > > > > > > I modified it per the pvops wiki page: ( > > http://wiki.xensource.com/xenwiki/XenParavirtOps) > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > root (hd0,0) > > kernel /xen-3.4.1-rc6.gz dom0_mem=512M > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root rhgb quiet > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > This looks correct.. > > > > > This is what is in my /etc/fstab: > > > > none /proc/xen xenfs defaults 0 0 > > > > > > So now I boot. When I boot the system the dom0 starts up instantly...., to > > the point where it says "scrubbing free ram" then the screen goes blank and > > all system activity ceases. > > > > Hmm.. try removing the "rhgb quiet" from the vmlinuz line in grub.conf. > > Is the last line you see something like this?: > > (XEN) Scrubbing Free RAM: ..........done. > > > You could also try adding "loglvl=all guest_loglvl=all noreboot" to the xen.gz line > to grub.conf. > > So try with this grub.conf: > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > root (hd0,0) > kernel /xen-3.4.1-rc6.gz dom0_mem=512M loglvl=all guest_loglvl=all noreboot > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > Has anyone tried these rpms? I am not sure if i can scream out "bug!" "bug!" > > because I cannot find anyone that has actually installed these rpms as part > > of a deployment process, (a workflow, a howto, a "step by step" edit "this" > > or edit "that".) so I am not sure if it is that I am missing a config > > parameter or not. > > > > I've used self-compiled pv_ops dom0 successfully on my testing box, but I > haven't really tried this RPMs.. > > If you don't > Heh.. forgot to finish this sentence. If you're having problems getting the console output from xen and/or pv_ops dom0 kernel, you should set up a serial console. There are instructions for that on the XenParavirtOps wiki page. -- Pasi From rjones at redhat.com Wed Jul 8 16:13:18 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 8 Jul 2009 17:13:18 +0100 Subject: [fedora-virt] New mailing list for libguestfs/guestfish/virt-inspector discussion/development Message-ID: <20090708161318.GA13152@amd.home.annexia.org> http://www.redhat.com/mailman/listinfo/libguestfs I'll be updating the website with the new details shortly. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From needwork at gmail.com Wed Jul 8 18:05:35 2009 From: needwork at gmail.com (Lester M.) Date: Wed, 8 Jul 2009 14:05:35 -0400 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <20090708144925.GX24960@edu.joroinen.fi> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> <20090708144925.GX24960@edu.joroinen.fi> Message-ID: <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> On Wed, Jul 8, 2009 at 10:49 AM, Pasi K?rkk?inen wrote: > On Wed, Jul 08, 2009 at 05:45:53PM +0300, Pasi K?rkk?inen wrote: > > On Wed, Jul 08, 2009 at 10:05:55AM -0400, Lester M. wrote: > > > > > > Thank you Pasi, > > > > > > Here is what my grub.conf entry looks like (with the xen-3.4.1 tools > > > compiled,) after you install all 4 rpms from myoung's fedorapeople > page: ( > > > http://fedorapeople.org/~myoung/dom0/ > > > > ) > > > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > > root (hd0,0) > > > kernel /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > > root=/dev/mapper/vg01-lv_root rhgb quiet nomodeset > > > initrd /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > > > > When you compile and install xen-3.4.1 the following is created in > /boot: > > > > > > -rw-r--r--. 1 root root 498660 2009-07-07 17:08 xen-3.4.1-rc6.gz > > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.4.gz -> > > > xen-3.4.1-rc6.gz > > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen-3.gz -> > > > xen-3.4.1-rc6.gz > > > lrwxrwxrwx. 1 root root 16 2009-07-07 17:08 xen.gz -> > xen-3.4.1-rc6.gz > > > > > > > > > I modified it per the pvops wiki page: ( > > > http://wiki.xensource.com/xenwiki/XenParavirtOps) > > > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > > root (hd0,0) > > > kernel /xen-3.4.1-rc6.gz dom0_mem=512M > > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > root=/dev/mapper/vg01-lv_root rhgb quiet > > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > > > > > This looks correct.. > > > > > > > > This is what is in my /etc/fstab: > > > > > > none /proc/xen xenfs defaults > 0 0 > > > > > > > > > So now I boot. When I boot the system the dom0 starts up instantly...., > to > > > the point where it says "scrubbing free ram" then the screen goes blank > and > > > all system activity ceases. > > > > > > > Hmm.. try removing the "rhgb quiet" from the vmlinuz line in grub.conf. > > > > Is the last line you see something like this?: > > > > (XEN) Scrubbing Free RAM: ..........done. > > > > > > You could also try adding "loglvl=all guest_loglvl=all noreboot" to the > xen.gz line > > to grub.conf. > > > > So try with this grub.conf: > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > root (hd0,0) > > kernel /xen-3.4.1-rc6.gz dom0_mem=512M loglvl=all guest_loglvl=all > noreboot > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > root=/dev/mapper/vg01-lv_root > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > > Has anyone tried these rpms? I am not sure if i can scream out "bug!" > "bug!" > > > because I cannot find anyone that has actually installed these rpms as > part > > > of a deployment process, (a workflow, a howto, a "step by step" edit > "this" > > > or edit "that".) so I am not sure if it is that I am missing a config > > > parameter or not. > > > > > > > I've used self-compiled pv_ops dom0 successfully on my testing box, but I > > haven't really tried this RPMs.. > > > > If you don't > > > > Heh.. forgot to finish this sentence. If you're having problems getting the > console output from xen and/or pv_ops dom0 kernel, you should set up a > serial console. > > There are instructions for that on the XenParavirtOps wiki page. > > -- Pasi > Hello Pasi, Unfortunately with adding "loglvl=all guest_loglvl=all noreboot" and removing "rhgb quiet" from the vmlinuz the result stayed the same. After the boot process gets to the "(XEN) Scrubbing Free RAM: ..........done." the screen still goes blank, and the system ceases to respond. This forces me to do a "hard reset" on my laptop. :-( This is my grub entry with the "loglvl=all guest_loglvl=all noreboot" added: title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all guest_loglvl=all com1=19200,8n1 console=com1 module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img When I set up a serial console and boot the system, the screen immediately goes "blank" and the system ceases to function as well. The difference is that this occurs sooner using the serial console than after the "(XEN) Scrubbing Free RAM: ..........done." occurrence. This is my grub entry with the serial console setup from the xenpvops page: title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all guest_loglvl=all com1=19200,8n1 console=com1 module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root console=hvc0 earlyprintk=xen module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img So all of this works on your system and not mine. Unfortunately this is all the hardware I am able to test on at this time. I don't know how many people are running this xen configuration on a Lenovo T60 laptop but there is clearly something missing. What more should I test to get this working? :-) Anything goes at this point, but I do hope the developers / maintainers are reading this thread. :-P -------------- next part -------------- An HTML attachment was scrubbed... URL: From m.a.young at durham.ac.uk Wed Jul 8 18:24:27 2009 From: m.a.young at durham.ac.uk (M A Young) Date: Wed, 8 Jul 2009 19:24:27 +0100 (BST) Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> Message-ID: On Wed, 8 Jul 2009, Lester M. wrote: > I downloaded the following rpms from M. Youngs fedora-people page. > (http://fedorapeople.org/~myoung/dom0/) > > kernel-firmware-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.noarch.rpm > kernel-headers-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i586.rpm > kernel-PAE-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > kernel-PAE-devel-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm Note that I have had trouble getting this kernel to boot on i686, though x86_64 seems okay. Michael Young From pasik at iki.fi Wed Jul 8 19:29:07 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 22:29:07 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> <20090708144925.GX24960@edu.joroinen.fi> <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> Message-ID: <20090708192907.GY24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 02:05:35PM -0400, Lester M. wrote: > > Hello Pasi, > > Unfortunately with adding "loglvl=all guest_loglvl=all noreboot" and > removing "rhgb quiet" from the vmlinuz the result stayed the same. > > After the boot process gets to the "(XEN) Scrubbing Free RAM: > ..........done." the screen still goes blank, and the system ceases to > respond. This forces me to do a "hard reset" on my laptop. :-( > Hmm.. The boot process should look something like this: .. (XEN) Scrubbing Free RAM: ..........done. (XEN) Xen trace buffers: disabled (XEN) Std. Loglevel: All (XEN) Guest Loglevel: All (XEN) *** Serial input -> DOM0 (type 'CTRL-a' three times to switch input to Xen) (XEN) Freed 104kB init memory. mapping kernel into physical memory Xen: setup ISA identity maps about to get started... Reserving virtual address space above 0xf5800000 PAT disabled on Xen Initializing cgroup subsys cpuset Initializing cgroup subsys cpu Linux version 2.6.30-rc6-tip (root at dom0test.localdomain) (gcc version 4.4.0 20090506 (Red Hat 4.4.0-4) (GCC) ) #15 SMP T ue Jun 9 19:36:50 EEST 2009 KERNEL supported cpus: Intel GenuineIntel AMD AuthenticAMD NSC Geode by NSC Cyrix CyrixInstead Centaur CentaurHauls Transmeta GenuineTMx86 Transmeta TransmetaCPU UMC UMC UMC UMC BIOS-provided physical RAM map: Xen: 0000000000000000 - 000000000009f400 (usable) Xen: 000000000009f400 - 0000000000100000 (reserved) Xen: 0000000000100000 - 0000000040000000 (usable) Xen: 000000007f6e0000 - 000000007f6e3000 (ACPI NVS) Xen: 000000007f6e3000 - 000000007f6f0000 (ACPI data) Xen: 000000007f6f0000 - 000000007f700000 (reserved) Xen: 00000000e0000000 - 00000000f0000000 (reserved) Xen: 00000000fec00000 - 0000000100000000 (reserved) console [xenboot0] enabled etc So the dom0 kernel should get booted up pretty shortly after that Scrubbing Free RAM.. > This is my grub entry with the "loglvl=all guest_loglvl=all noreboot" added: > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > root (hd0,0) > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all guest_loglvl=all > com1=19200,8n1 console=com1 > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > root=/dev/mapper/vg01-lv_root > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > You shouldn't have the "com1=19200,8n1 console=com1" there if you want to use the VGA text console.. > > > When I set up a serial console and boot the system, the screen immediately > goes "blank" and the system ceases to function as well. The difference is > that this occurs sooner using the serial console than after the "(XEN) > Scrubbing Free RAM: ..........done." occurrence. > When you have a serial console in use, the screen _should_ go blank immediately, because the console output is redirected to the serial port/console. So the behaviour you're seeing there is expected. > This is my grub entry with the serial console setup from the xenpvops page: > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > root (hd0,0) > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all guest_loglvl=all > com1=19200,8n1 console=com1 > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > root=/dev/mapper/vg01-lv_root console=hvc0 earlyprintk=xen > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > That looks correct, if your laptop serial port actually is com1. Do you see the Xen and dom0 kernel boot messages on the serial console? > > So all of this works on your system and not mine. Unfortunately this is all > the hardware I am able to test on at this time. I don't know how many people > are running this xen configuration on a Lenovo T60 laptop but there is > clearly something missing. > > What more should I test to get this working? :-) Anything goes at this > point, but I do hope the developers / maintainers are reading this thread. > :-P Do you have to specify any non-default parameters to xen or dom0 kernel when you use RHEL 5.3 on the laptop? -- Pasi From pasik at iki.fi Wed Jul 8 19:33:45 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 22:33:45 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> Message-ID: <20090708193345.GZ24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 07:24:27PM +0100, M A Young wrote: > On Wed, 8 Jul 2009, Lester M. wrote: > > >I downloaded the following rpms from M. Youngs fedora-people page. > >(http://fedorapeople.org/~myoung/dom0/) > > > >kernel-firmware-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.noarch.rpm > >kernel-headers-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i586.rpm > >kernel-PAE-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > >kernel-PAE-devel-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.rpm > > Note that I have had trouble getting this kernel to boot on i686, though > x86_64 seems okay. > Hmm.. I wonder what's wrong there. My custom pv_ops dom0 kernel boots just fine on i686.. My .config is here: http://pasik.reaktio.net/xen/pv_ops-dom0-debug/config-2.6.30-rc6-tip-next-with-highpte CONFIG_HIGHPTE is enabled on that config, but I disable it (CONFIG_HIGHPTE=n) to workaround the race in xen_set_pte() until it's fixed properly. -- Pasi From needwork at gmail.com Wed Jul 8 19:58:44 2009 From: needwork at gmail.com (Lester M.) Date: Wed, 8 Jul 2009 15:58:44 -0400 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <20090708192907.GY24960@edu.joroinen.fi> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> <20090708144925.GX24960@edu.joroinen.fi> <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> <20090708192907.GY24960@edu.joroinen.fi> Message-ID: <2cc75dd80907081258r4abbf481v3f740f77f797e763@mail.gmail.com> On Wed, Jul 8, 2009 at 3:29 PM, Pasi K?rkk?inen wrote: > On Wed, Jul 08, 2009 at 02:05:35PM -0400, Lester M. wrote: > > > > Hello Pasi, > > > > Unfortunately with adding "loglvl=all guest_loglvl=all noreboot" and > > removing "rhgb quiet" from the vmlinuz the result stayed the same. > > > > After the boot process gets to the "(XEN) Scrubbing Free RAM: > > ..........done." the screen still goes blank, and the system ceases to > > respond. This forces me to do a "hard reset" on my laptop. :-( > > > > Hmm.. The boot process should look something like this: > > .. > (XEN) Scrubbing Free RAM: ..........done. > (XEN) Xen trace buffers: disabled > (XEN) Std. Loglevel: All > (XEN) Guest Loglevel: All > (XEN) *** Serial input -> DOM0 (type 'CTRL-a' three times to switch input > to Xen) > (XEN) Freed 104kB init memory. > mapping kernel into physical memory > Xen: setup ISA identity maps > about to get started... > Reserving virtual address space above 0xf5800000 > PAT disabled on Xen > Initializing cgroup subsys cpuset > Initializing cgroup subsys cpu > Linux version 2.6.30-rc6-tip (root at dom0test.localdomain) (gcc version > 4.4.0 > 20090506 (Red Hat 4.4.0-4) (GCC) ) #15 SMP T > ue Jun 9 19:36:50 EEST 2009 > KERNEL supported cpus: > Intel GenuineIntel > AMD AuthenticAMD > NSC Geode by NSC > Cyrix CyrixInstead > Centaur CentaurHauls > Transmeta GenuineTMx86 > Transmeta TransmetaCPU > UMC UMC UMC UMC > BIOS-provided physical RAM map: > Xen: 0000000000000000 - 000000000009f400 (usable) > Xen: 000000000009f400 - 0000000000100000 (reserved) > Xen: 0000000000100000 - 0000000040000000 (usable) > Xen: 000000007f6e0000 - 000000007f6e3000 (ACPI NVS) > Xen: 000000007f6e3000 - 000000007f6f0000 (ACPI data) > Xen: 000000007f6f0000 - 000000007f700000 (reserved) > Xen: 00000000e0000000 - 00000000f0000000 (reserved) > Xen: 00000000fec00000 - 0000000100000000 (reserved) > console [xenboot0] enabled > > etc > > So the dom0 kernel should get booted up pretty shortly after that Scrubbing > Free RAM.. > > > > This is my grub entry with the "loglvl=all guest_loglvl=all noreboot" > added: > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > root (hd0,0) > > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all > guest_loglvl=all > > com1=19200,8n1 console=com1 > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > root=/dev/mapper/vg01-lv_root > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > You shouldn't have the "com1=19200,8n1 console=com1" there if you want to > use > the VGA text console.. > > > > > > > When I set up a serial console and boot the system, the screen > immediately > > goes "blank" and the system ceases to function as well. The difference is > > that this occurs sooner using the serial console than after the "(XEN) > > Scrubbing Free RAM: ..........done." occurrence. > > > > When you have a serial console in use, the screen _should_ go blank > immediately, > because the console output is redirected to the serial port/console. > > So the behaviour you're seeing there is expected. > > > This is my grub entry with the serial console setup from the xenpvops > page: > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > root (hd0,0) > > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all > guest_loglvl=all > > com1=19200,8n1 console=com1 > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > root=/dev/mapper/vg01-lv_root console=hvc0 earlyprintk=xen > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > That looks correct, if your laptop serial port actually is com1. > Do you see the Xen and dom0 kernel boot messages on the serial console? > > > > > So all of this works on your system and not mine. Unfortunately this is > all > > the hardware I am able to test on at this time. I don't know how many > people > > are running this xen configuration on a Lenovo T60 laptop but there is > > clearly something missing. > > > > What more should I test to get this working? :-) Anything goes at this > > point, but I do hope the developers / maintainers are reading this > thread. > > :-P > > Do you have to specify any non-default parameters to xen or dom0 kernel > when > you use RHEL 5.3 on the laptop? > > -- Pasi > Pasi, and M A Young; Thank you so much for the information thus far, I really appreciate the feedback in resolving this. :-) What Kernel options should I use to get a vga console? (to just have *everything* dump on my screen?) I do not have a "real" serial console on my consumer laptop. On RHEL 5.3 I have no extra options than the defaults (which includes the "rhgb quiet" on the vmlinuz line), it just boots! I took a look at that earlier. I will try out your 32bit .config, did you get your kernel checkout from: (git clone git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.gitlinux-2.6-xen) ? Also, did you use the latest branch? (from: git checkout origin/xen-tip/next -b xen-tip/next) ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From pasik at iki.fi Wed Jul 8 20:54:56 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Wed, 8 Jul 2009 23:54:56 +0300 Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <2cc75dd80907081258r4abbf481v3f740f77f797e763@mail.gmail.com> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> <20090708144925.GX24960@edu.joroinen.fi> <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> <20090708192907.GY24960@edu.joroinen.fi> <2cc75dd80907081258r4abbf481v3f740f77f797e763@mail.gmail.com> Message-ID: <20090708205456.GC24960@edu.joroinen.fi> On Wed, Jul 08, 2009 at 03:58:44PM -0400, Lester M. wrote: > On Wed, Jul 8, 2009 at 3:29 PM, Pasi K?rkk?inen wrote: > > > On Wed, Jul 08, 2009 at 02:05:35PM -0400, Lester M. wrote: > > > > > > Hello Pasi, > > > > > > Unfortunately with adding "loglvl=all guest_loglvl=all noreboot" and > > > removing "rhgb quiet" from the vmlinuz the result stayed the same. > > > > > > After the boot process gets to the "(XEN) Scrubbing Free RAM: > > > ..........done." the screen still goes blank, and the system ceases to > > > respond. This forces me to do a "hard reset" on my laptop. :-( > > > > > > > Hmm.. The boot process should look something like this: > > > > .. > > (XEN) Scrubbing Free RAM: ..........done. > > (XEN) Xen trace buffers: disabled > > (XEN) Std. Loglevel: All > > (XEN) Guest Loglevel: All > > (XEN) *** Serial input -> DOM0 (type 'CTRL-a' three times to switch input > > to Xen) > > (XEN) Freed 104kB init memory. > > mapping kernel into physical memory > > Xen: setup ISA identity maps > > about to get started... > > Reserving virtual address space above 0xf5800000 > > PAT disabled on Xen > > Initializing cgroup subsys cpuset > > Initializing cgroup subsys cpu > > Linux version 2.6.30-rc6-tip (root at dom0test.localdomain) (gcc version > > 4.4.0 > > 20090506 (Red Hat 4.4.0-4) (GCC) ) #15 SMP T > > ue Jun 9 19:36:50 EEST 2009 > > KERNEL supported cpus: > > Intel GenuineIntel > > AMD AuthenticAMD > > NSC Geode by NSC > > Cyrix CyrixInstead > > Centaur CentaurHauls > > Transmeta GenuineTMx86 > > Transmeta TransmetaCPU > > UMC UMC UMC UMC > > BIOS-provided physical RAM map: > > Xen: 0000000000000000 - 000000000009f400 (usable) > > Xen: 000000000009f400 - 0000000000100000 (reserved) > > Xen: 0000000000100000 - 0000000040000000 (usable) > > Xen: 000000007f6e0000 - 000000007f6e3000 (ACPI NVS) > > Xen: 000000007f6e3000 - 000000007f6f0000 (ACPI data) > > Xen: 000000007f6f0000 - 000000007f700000 (reserved) > > Xen: 00000000e0000000 - 00000000f0000000 (reserved) > > Xen: 00000000fec00000 - 0000000100000000 (reserved) > > console [xenboot0] enabled > > > > etc > > > > So the dom0 kernel should get booted up pretty shortly after that Scrubbing > > Free RAM.. > > > > > > > This is my grub entry with the "loglvl=all guest_loglvl=all noreboot" > > added: > > > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > > root (hd0,0) > > > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all > > guest_loglvl=all > > > com1=19200,8n1 console=com1 > > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > > root=/dev/mapper/vg01-lv_root > > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > > You shouldn't have the "com1=19200,8n1 console=com1" there if you want to > > use > > the VGA text console.. > > > > > > > > > > > When I set up a serial console and boot the system, the screen > > immediately > > > goes "blank" and the system ceases to function as well. The difference is > > > that this occurs sooner using the serial console than after the "(XEN) > > > Scrubbing Free RAM: ..........done." occurrence. > > > > > > > When you have a serial console in use, the screen _should_ go blank > > immediately, > > because the console output is redirected to the serial port/console. > > > > So the behaviour you're seeing there is expected. > > > > > This is my grub entry with the serial console setup from the xenpvops > > page: > > > > > > title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) > > > root (hd0,0) > > > kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all > > guest_loglvl=all > > > com1=19200,8n1 console=com1 > > > module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro > > > root=/dev/mapper/vg01-lv_root console=hvc0 earlyprintk=xen > > > module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img > > > > > > > That looks correct, if your laptop serial port actually is com1. > > Do you see the Xen and dom0 kernel boot messages on the serial console? > > > > > > > > So all of this works on your system and not mine. Unfortunately this is > > all > > > the hardware I am able to test on at this time. I don't know how many > > people > > > are running this xen configuration on a Lenovo T60 laptop but there is > > > clearly something missing. > > > > > > What more should I test to get this working? :-) Anything goes at this > > > point, but I do hope the developers / maintainers are reading this > > thread. > > > :-P > > > > Do you have to specify any non-default parameters to xen or dom0 kernel > > when > > you use RHEL 5.3 on the laptop? > > > > -- Pasi > > > > Pasi, and M A Young; > > Thank you so much for the information thus far, I really appreciate the > feedback in resolving this. :-) > > What Kernel options should I use to get a vga console? (to just have > *everything* dump on my screen?) I do not have a "real" serial console on my > consumer laptop. > For VGA text console: title Fedora (2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE) root (hd0,0) kernel /xen-3.4.1-rc6.gz dom0_mem=1024M loglvl=all guest_loglvl=all noreboot module /vmlinuz-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE ro root=/dev/mapper/vg01-lv_root nomodeset module /initrd-2.6.31-0.1.2.37.rc1.git5.xendom0.fc12.i686.PAE.img That should work. Serial console is good for debugging problems like this.. but if you don't have a serial port on the laptop, then you can't use it obviously :) > On RHEL 5.3 I have no extra options than the defaults (which includes the > "rhgb quiet" on the vmlinuz line), it just boots! I took a look at that > earlier. > > I will try out your 32bit .config, did you get your kernel checkout from: > (git clone git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.gitlinux-2.6-xen) > ? > > Also, did you use the latest branch? (from: git checkout origin/xen-tip/next > -b xen-tip/next) ? I used "xen-tip/next". Although there's a newer branch available after that.. "rebase/master", but I don't know in which shape that is. -- Pasi From m.a.young at durham.ac.uk Wed Jul 8 21:16:42 2009 From: m.a.young at durham.ac.uk (M A Young) Date: Wed, 8 Jul 2009 22:16:42 +0100 (BST) Subject: [fedora-virt] pv_ops dom0 kernel RPM, configuration & setup help anyone? In-Reply-To: <20090708205456.GC24960@edu.joroinen.fi> References: <2cc75dd80907071822u1336ddadv9f61a25f33b45dcc@mail.gmail.com> <20090708103230.GS24960@edu.joroinen.fi> <2cc75dd80907080705r75b227f1icd8dd7022e1df73f@mail.gmail.com> <20090708144553.GW24960@edu.joroinen.fi> <20090708144925.GX24960@edu.joroinen.fi> <2cc75dd80907081105o48b764f7s59c7330d4854c049@mail.gmail.com> <20090708192907.GY24960@edu.joroinen.fi> <2cc75dd80907081258r4abbf481v3f740f77f797e763@mail.gmail.com> <20090708205456.GC24960@edu.joroinen.fi> Message-ID: On Wed, 8 Jul 2009, Pasi K?rkk?inen wrote: > I used "xen-tip/next". > > Although there's a newer branch available after that.. "rebase/master", but > I don't know in which shape that is. That is what my kernels are built against, so it looks like rebase/master is close but not quite there yet (or at least wasn't when I last built from it). Michael Young From bret381 at gmail.com Fri Jul 10 14:27:39 2009 From: bret381 at gmail.com (Bret Rusnak) Date: Fri, 10 Jul 2009 10:27:39 -0400 Subject: [fedora-virt] kvm/qemu network problem Message-ID: <4A574FDB.7080106@gmail.com> In installed win xp and everything installed fine, however my virtual network card is not getting an ip address from my router. It is showing up as a realtek RTL 8139 network card and is showing that the device is working properly. Anyone had similar issues or have a way to fix this? Thanks in advance From m.a.young at durham.ac.uk Fri Jul 10 23:11:08 2009 From: m.a.young at durham.ac.uk (M A Young) Date: Sat, 11 Jul 2009 00:11:08 +0100 (BST) Subject: [fedora-virt] Re: [Fedora-xen] Dom0 kernels In-Reply-To: References: <20090328163545.GM31725@salstar.sk> <20090414143618.GH351@redhat.com> Message-ID: Here is another update (kernel-2.6.31-0.1.2.40.rc2.git4.xendom0.fc12) at http://koji.fedoraproject.org/koji/taskinfo?taskID=1466158 and the repository http://fedorapeople.org/~myoung/dom0/ . This updates to the latest rawhide source, I don't think there are significant changes on the xen side, so i686 may still be broken, though the x86_64 version works okay for me. Michael Young From eb30750 at gmail.com Sat Jul 11 22:38:56 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sat, 11 Jul 2009 18:38:56 -0400 Subject: [fedora-virt] Virt USB issues (doesn't work without customizing) Message-ID: <4A591480.3040505@gmail.com> Lot's of blog material out there. Trying to get ext. USB disk to map in Windows virt image. Here is where I am. 1) I found a link to someone who did get external USB disks working with FE.11 Virt the issues that prevent this from working by just adding the hardware through the virt manager are: a) need selinux-policy-target-3.6.12-62.fcc11.noarch or later b) selinux blocks access to this device and must be customized. 2) OK, this should take that long. (or should it?) a) went to add/remove software through Gnome and did not find any pending updates for selinux. b) after searching for another hour found how to command line Yum for selinux updates. Here's what I got. [root at BRSINC-VC01 qemu]# rpm -qa | grep selinux libselinux-utils-2.0.80-1.fc11.i586 libselinux-python-2.0.80-1.fc11.i586 selinux-policy-targeted-3.6.12-53.fc11.noarch libselinux-2.0.80-1.fc11.i586 selinux-policy-3.6.12-53.fc11.noarch [root at BRSINC-VC01 qemu]# yum -y upgrade selinux-policy-targeted Loaded plugins: refresh-packagekit rpmfusion-nonfree-updates | 3.8 kB 00:00 updates/metalink | 23 kB 00:01 Setting up Upgrade Process No Packages marked for Update Based on this I would assume there are no updates even though others claim there are. Where is 62 and why does it not show up in the Gnome software update tool? From eb30750 at gmail.com Sat Jul 11 22:44:19 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sat, 11 Jul 2009 18:44:19 -0400 Subject: [fedora-virt] Update on virtio network driver performance Message-ID: <4A5915C3.7090205@gmail.com> Just some feedback for Rich on performance after switching to virtio network driver. Before both cpus were running at 70-90%. After virtio driver cpus running 20-30%. That's something like 67% less loading. The real test is whether the keyboard, mouse and window dragging "shadow" or delay when moving. This is much better but not equal to that of performing these functions on the host machine. OK, so where's the virtio drivers for Windows? I found a link dated early March that stated they were coming soon. Can't find them anywhere. PJAL From eb30750 at gmail.com Sat Jul 11 23:01:16 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sat, 11 Jul 2009 19:01:16 -0400 Subject: [fedora-virt] KVM update available? Message-ID: <4A5919BC.70800@gmail.com> On the SourceForge page there is a new Fedora KVM release 87 available. No date, no version. When I open add/remove software under Gnome (Fedora 11) I find that I have QEMU system emulator x86-2:0.10.5-3.fc11 installed and x86-2:0.10-16.fc11 available. This looks like a newer verion but how to I know? There is no release date or release version shown in the lower right pane where the package information is shown. Additionally, the 10.5-3 versus 10-16 versioning makes me hesitate since I am not sure these are one in the same package. Several problems here that are all contributing to the amount of blog and Email traffic: Consistent documentation and identification of what is current. If the two packages are the same and 10-16 is an update then it should be 10.16-0(?) for consistency. Should I install this update? PJAL From eb30750 at gmail.com Sat Jul 11 20:42:41 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sat, 11 Jul 2009 16:42:41 -0400 Subject: [fedora-virt] Addendum to USB issues Message-ID: Should have included this in the first Email. Below is the boolean output of getsebool. Note that the qemu_use fields do have permission to access USB but there is no USB entry for the virt though there is for other virt_fields. I am running the Looks to me some migration leftovers from qemu to qemu-kvm. Since I do not have the virt_use_usb selinux field I do need the most recent update that includes this. I am running: [root at BRSINC-VC01 EB30750]# uname -a Linux BRSINC-VC01.Local 2.6.29.5-191.fc11.i586 #1 SMP Tue Jun 16 23:11:39 EDT 2009 i686 athlon i386 GNU/Linux [root at BRSINC-VC01 EB30750]# getsebool -a allow_console_login --> off allow_cvs_read_shadow --> off allow_daemons_dump_core --> on allow_daemons_use_tty --> on allow_domain_fd_use --> on allow_execheap --> off allow_execmem --> off allow_execmod --> off allow_execstack --> on allow_ftpd_anon_write --> off allow_ftpd_full_access --> off allow_ftpd_use_cifs --> off allow_ftpd_use_nfs --> off allow_gssd_read_tmp --> on allow_guest_exec_content --> off allow_httpd_anon_write --> off allow_httpd_mod_auth_ntlm_winbind --> off allow_httpd_mod_auth_pam --> off allow_httpd_sys_script_anon_write --> off allow_java_execstack --> off allow_kerberos --> on allow_mount_anyfile --> on allow_mplayer_execstack --> off allow_nfsd_anon_write --> off allow_nsplugin_execmem --> on allow_polyinstantiation --> off allow_postfix_local_write_mail_spool --> on allow_ptrace --> off allow_rsync_anon_write --> off allow_saslauthd_read_shadow --> off allow_smbd_anon_write --> off allow_ssh_keysign --> off allow_staff_exec_content --> on allow_sysadm_exec_content --> on allow_unconfined_mmap_low --> off allow_unconfined_nsplugin_transition --> off allow_unconfined_qemu_transition --> off allow_user_exec_content --> on allow_user_postgresql_connect --> off allow_write_xshm --> off allow_xguest_exec_content --> off allow_xserver_execmem --> on allow_ypbind --> off allow_zebra_write_config --> on cdrecord_read_content --> off cron_can_relabel --> off exim_can_connect_db --> off exim_manage_user_files --> off exim_read_user_files --> off fcron_crond --> off ftp_home_dir --> off ftpd_connect_db --> off global_ssp --> off gpg_agent_env_file --> off httpd_builtin_scripting --> on httpd_can_network_connect --> off httpd_can_network_connect_db --> off httpd_can_network_relay --> off httpd_can_sendmail --> off httpd_dbus_avahi --> on httpd_enable_cgi --> on httpd_enable_ftp_server --> off httpd_enable_homedirs --> on httpd_execmem --> off httpd_ssi_exec --> off httpd_tty_comm --> on httpd_unified --> on httpd_use_cifs --> off httpd_use_nfs --> off init_upstart --> on mozilla_read_content --> off named_write_master_zones --> off nfs_export_all_ro --> on nfs_export_all_rw --> on nsplugin_can_network --> on openvpn_enable_homedirs --> off pppd_can_insmod --> off pppd_for_user --> off privoxy_connect_any --> off pulseaudio_network --> off qemu_full_network --> on qemu_use_cifs --> on qemu_use_comm --> off qemu_use_nfs --> on qemu_use_usb --> on read_default_t --> on rsync_client --> off rsync_export_all_ro --> off samba_create_home_dirs --> off samba_domain_controller --> off samba_enable_home_dirs --> off samba_export_all_ro --> off samba_export_all_rw --> off samba_run_unconfined --> on samba_share_fusefs --> off samba_share_nfs --> off secure_mode --> off secure_mode_insmod --> off secure_mode_policyload --> off sepgsql_enable_users_ddl --> on spamassassin_can_network --> off spamd_enable_home_dirs --> on squid_connect_any --> off ssh_sysadm_login --> off tftp_anon_write --> off unconfined_login --> on use_lpd_server --> off use_nfs_home_dirs --> on use_samba_home_dirs --> off user_direct_mouse --> off user_ping --> on user_rw_noexattrfile --> on user_tcp_server --> off user_ttyfile_stat --> off varnishd_connect_any --> off virt_manage_sysfs --> off virt_use_comm --> off virt_use_nfs --> off virt_use_samba --> off webadm_manage_user_files --> off webadm_read_user_files --> off xdm_sysadm_login --> off xen_use_nfs --> off xguest_connect_network --> on xguest_mount_media --> on xguest_use_bluetooth --> on xserver_object_manager --> off From giallu at gmail.com Sat Jul 11 22:01:34 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Sun, 12 Jul 2009 00:01:34 +0200 Subject: [fedora-virt] Virt USB issues (doesn't work without customizing) In-Reply-To: <4A591480.3040505@gmail.com> References: <4A591480.3040505@gmail.com> Message-ID: On Sun, Jul 12, 2009 at 12:38 AM, Paul Lambert wrote: > 1) I found a link to someone who did get external USB disks working with > FE.11 Virt the issues that prevent this from working by just adding the > hardware through the virt manager are: > a) need selinux-policy-target-3.6.12-62.fcc11.noarch or later > b) selinux blocks access to this device and must be customized. > Search archive for the recent thres "USB passthrough", I guess it would be of some help. > > Based on this ?I would assume there are no updates even though others claim > there are. ?Where is 62 and why does it not show up in the Gnome software > update tool? That update was probably in "updates-testing" so you should have run something like: yum --enablerepo=updates-testing update selinux-policy-targeted In the meantime it seems it got pushed to stable so you should be able to find the package with a regular yum update (I'm downloading it right now) -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From giallu at gmail.com Sun Jul 12 07:44:54 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Sun, 12 Jul 2009 09:44:54 +0200 Subject: [fedora-virt] Virt USB issues (doesn't work without customizing) In-Reply-To: References: <4A591480.3040505@gmail.com> Message-ID: On Sun, Jul 12, 2009 at 4:39 AM, Paul Lambert wrote: > Thanks for the tip. ?Yes, I was able to get the selinux software > updated. But, I do believe the Gnome software should allow for > alternative hosts to be selected to download from other sites than > just the main Fedora page. I am not sure what you mean but both the gnome updater (PackageKit) and the CLI one (yum) picks from fedora servers a list of mirrors and downloads from them, all without user intervention. > > After relaunching virt I did get past the selinux error but now I am > getting blocked at the USB device with could not add the usb host . > /proc/bus/usb/002/001 and 004. ?This appears to be directory > permission error. ?Root has rw but root group on only r. ?I switched > to root when launching virt manager so I should be OK anyway. ?Made > any progress yourself? I did not test this stuff myself, sorry. Please when replying make sure you hit "reply all" otherwise you're not replying to list -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From rjones at redhat.com Sun Jul 12 11:24:50 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sun, 12 Jul 2009 12:24:50 +0100 Subject: [fedora-virt] Update on virtio network driver performance In-Reply-To: <4A5915C3.7090205@gmail.com> References: <4A5915C3.7090205@gmail.com> Message-ID: <20090712112450.GA17404@amd.home.annexia.org> On Sat, Jul 11, 2009 at 06:44:19PM -0400, Paul Lambert wrote: > OK, so where's the virtio drivers for Windows? I found a link dated > early March that stated they were coming soon. Can't find them > anywhere. Last time I looked there was a virtio network driver for Windows. The virtio block driver for Windows was (and I think still is) under development. In the meantime, use a network-attached storage device. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Sun Jul 12 11:25:44 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sun, 12 Jul 2009 12:25:44 +0100 Subject: [fedora-virt] KVM update available? In-Reply-To: <4A5919BC.70800@gmail.com> References: <4A5919BC.70800@gmail.com> Message-ID: <20090712112544.GB17404@amd.home.annexia.org> On Sat, Jul 11, 2009 at 07:01:16PM -0400, Paul Lambert wrote: > On the SourceForge page there is a new Fedora KVM release 87 available. > No date, no version. Which is this SourceForge page? Fedora doesn't distribute any packages through SF. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 75 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora From eb30750 at gmail.com Sun Jul 12 15:35:59 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sun, 12 Jul 2009 11:35:59 -0400 Subject: [fedora-virt] cannot mount USB disks even after selinux update for Windows VM Message-ID: I have searched the bug list to resolve this problem and after making the same changes as others still am not able to get external USB disks to mount to my Windows virt machine. current versions qemu-system-x86-2.0.10.5-3.fc11 selinux-policy-doc-3..6.12.62.fc11 1) The first problem encountered was a SELinux matter that updating to .62 corrected. There was no virt_use_usb parameter in the version that was previously installed. The absence of this SELinux permission disallowed access to /sbin/ifconig generating a selinux permission error 2) Next I received a "broken pipe" error. I then tried commenting out the line containing "nss_initgroups_ignoreusers" in /etc/ldap.conf which was documented in the bug list and has worked for others. This did not work for me. Current status is the shown below from the virt machine log file. LC_ALL=C PATH=/sbin:/usr/sbin:/bin:/usr/bin /usr/bin/qemu-kvm -S -M pc -m 768 -s mp 2 -name Windows-XP-SP3-Home -uuid ee3bc9fe-a724-45b5-b675-11251f5c453f -monit or pty -pidfile /var/run/libvirt/qemu//Windows-XP-SP3-Home.pid -boot c -drive fi le=/var/lib/libvirt/images/Windows-XP-SP3-Home.img,if=ide,index=0,boot=on -drive file=,if=ide,media=cdrom,index=2 -net nic,macaddr=54:52:00:7e:1c:92,vlan=0,mode l=virtio -net tap,fd=17,vlan=0 -serial pty -parallel none -usb -usbdevice tablet -vnc 127.0.0.1:0 -usbdevice host:1d6b:0002 char device redirected to /dev/pts/0 char device redirected to /dev/pts/1 husb: open device 2.1 husb: config #1 need -1 husb: 1 interfaces claimed for configuration 1 husb: grabbed usb device 2.1 usb_linux_update_endp_table: Broken pipe Warning: could not add USB device host:1d6b:0002 From rjones at redhat.com Sun Jul 12 22:20:24 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sun, 12 Jul 2009 23:20:24 +0100 Subject: [fedora-virt] cannot mount USB disks even after selinux update for Windows VM In-Reply-To: References: Message-ID: <20090712222024.GA19118@amd.home.annexia.org> On Sun, Jul 12, 2009 at 11:35:59AM -0400, Paul Lambert wrote: > I have searched the bug list to resolve this problem and after making > the same changes as others still am not able to get external USB disks > to mount to my Windows virt machine. You've read Mark's thread? http://www.redhat.com/archives/fedora-virt/2009-June/msg00182.html Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From needwork at gmail.com Mon Jul 13 01:59:09 2009 From: needwork at gmail.com (Lester M.) Date: Sun, 12 Jul 2009 21:59:09 -0400 Subject: [fedora-virt] Re: [Fedora-xen] Dom0 kernels In-Reply-To: References: Message-ID: <2cc75dd80907121859q227e715w2278f37568d73d41@mail.gmail.com> On Fri, Jul 10, 2009 at 7:11 PM, M A Young wrote: > Here is another update (kernel-2.6.31-0.1.2.40.rc2.git4.xendom0.fc12) at > http://koji.fedoraproject.org/koji/taskinfo?taskID=1466158 and the > repository http://fedorapeople.org/~myoung/dom0/. This updates to the latest rawhide source, I don't think there are > significant changes on the xen side, so i686 may still be broken, though the > x86_64 version works okay for me. > > Michael Young > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt > Hello Michael, I can confirm my same issue is still present. I used your latest updated kernels (i686), still get a "Blank Screen", unresponsive system, that require a hard reset. Was not able to get output after xen says "Scrubbing free memory.......Done." I'll keep testing for ya, as you release them. :-) -------------- next part -------------- An HTML attachment was scrubbed... URL: From eb30750 at gmail.com Mon Jul 13 02:29:16 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sun, 12 Jul 2009 22:29:16 -0400 Subject: [fedora-virt] cannot mount USB disks even after selinux update for Windows VM: UPDATE Message-ID: Yes, I saw Mark's comments yesterday. I now have a USB disk working as prescribed. The issue was due to adding the Linux Foundation USB 2.0 hardware when I actually had the ext USB disk plugged into the one USB port that is part of a JM20336, Sata, USB Combo. Once I added this hardware I did get the USB disk to work. I then tested the ext USB disk on the other two USB ports that use the Linux Foundation USB 2.0 drivers. They both worked too. I would second the comment to Bug#508645 to make the USB devices dynamic if the managed field is set to yes. This should be done by implementing a button or checkbox ("auto connect enable") on the details page of the VM when the specific USB hardware is selected. Similar to the CDROM "connect" button. Can the --usbdevice host:auto:*:*:xxxx:xxxx statement be hacked into the KVM startup script somewhere or is this a feature for the next release? Though solving the ext USB disk matter, it created another one in the process. While I was at it I connected my ext disk via the eSata connection on my laptop just for kicks. The ext. case has dual connections, USB/eSATA. I noticed when I went back to add the hardware to the VM that the "Sata" and "USB" references were now gone. This might be a Fedora matter first since the ext. disk does not mount to it either. Needless to say, the Windows VM did not see the eSata ext disk either. The eSata bug appears to be reported in bug#485666. The combo interface is a JM20366 Dual sata/usb interface; http://www.jmicron.com/JM20336.html. Getting SATA to work is important since running more than a few VMs on the same disk won't make it. I searched around for Linux drivers for this device and only could find that these should already be part of the Linux distro. Note: [There is strange behavior when adding and removing hardware. I went back to repeat my steps and removed the JM20336 combo which was installed as a USB device. When I went back to re-install it, the entry for the hardware device was not there. I then deleted the other USB device and rebooted. Still nothing. Finally I added the Logitech Camera that was also a part of the combo and then removed it. Presto, they all reappeared. I then added the Sata/USB combo and then went back to add additional hardware. The Sata/USB was still listed. I added it again then there were two entries for the same device in the .xml file. I deleted it again and the re-added it. After this it was not listed in the available hardware. I have experienced similar such things when adding/removing hardware.] On 7/12/09, Richard W.M. Jones wrote: > On Sun, Jul 12, 2009 at 11:35:59AM -0400, Paul Lambert wrote: >> I have searched the bug list to resolve this problem and after making >> the same changes as others still am not able to get external USB disks >> to mount to my Windows virt machine. > > You've read Mark's thread? > > http://www.redhat.com/archives/fedora-virt/2009-June/msg00182.html > > Rich. > > -- > Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones > virt-top is 'top' for virtual machines. Tiny program with many > powerful monitoring features, net stats, disk stats, logging, etc. > http://et.redhat.com/~rjones/virt-top > From berrange at redhat.com Mon Jul 13 08:57:37 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 13 Jul 2009 09:57:37 +0100 Subject: [fedora-virt] KVM update available? In-Reply-To: <4A5919BC.70800@gmail.com> References: <4A5919BC.70800@gmail.com> Message-ID: <20090713085737.GA21199@redhat.com> On Sat, Jul 11, 2009 at 07:01:16PM -0400, Paul Lambert wrote: > On the SourceForge page there is a new Fedora KVM release 87 available. > No date, no version. kvm-XXX numbering scheme is the unstable development snapshot branch. Fedora uses the stable branch, which matches the QEMU numbering scheme, qemu-kvm-0.10.x Thus there are no plans to ship kvm-87 or any other kvm-XX release series Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From dlaor at redhat.com Mon Jul 13 09:13:51 2009 From: dlaor at redhat.com (Dor Laor) Date: Mon, 13 Jul 2009 12:13:51 +0300 Subject: [fedora-virt] Update on virtio network driver performance In-Reply-To: <20090712112450.GA17404@amd.home.annexia.org> References: <4A5915C3.7090205@gmail.com> <20090712112450.GA17404@amd.home.annexia.org> Message-ID: <4A5AFACF.1050002@redhat.com> On 07/12/2009 02:24 PM, Richard W.M. Jones wrote: > On Sat, Jul 11, 2009 at 06:44:19PM -0400, Paul Lambert wrote: >> OK, so where's the virtio drivers for Windows? I found a link dated >> early March that stated they were coming soon. Can't find them >> anywhere. > > Last time I looked there was a virtio network driver for Windows. The > virtio block driver for Windows was (and I think still is) under > development. In the meantime, use a network-attached storage device. > > Rich. > In the near future (month+-) we plan to release both drivers for windows. Regards, Dor From pasik at iki.fi Mon Jul 13 11:05:50 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Mon, 13 Jul 2009 14:05:50 +0300 Subject: [fedora-virt] Re: [Fedora-xen] Dom0 kernels In-Reply-To: <2cc75dd80907121859q227e715w2278f37568d73d41@mail.gmail.com> References: <2cc75dd80907121859q227e715w2278f37568d73d41@mail.gmail.com> Message-ID: <20090713110550.GP24960@edu.joroinen.fi> On Sun, Jul 12, 2009 at 09:59:09PM -0400, Lester M. wrote: > On Fri, Jul 10, 2009 at 7:11 PM, M A Young wrote: > > > Here is another update (kernel-2.6.31-0.1.2.40.rc2.git4.xendom0.fc12) at > > http://koji.fedoraproject.org/koji/taskinfo?taskID=1466158 and the > > repository http://fedorapeople.org/~myoung/dom0/. This updates to the latest rawhide source, I don't think there are > > significant changes on the xen side, so i686 may still be broken, though the > > x86_64 version works okay for me. > > > > Michael Young > > > > _______________________________________________ > > Fedora-virt mailing list > > Fedora-virt at redhat.com > > https://www.redhat.com/mailman/listinfo/fedora-virt > > > > > Hello Michael, > > I can confirm my same issue is still present. I used your latest updated > kernels (i686), still get a "Blank Screen", unresponsive system, that > require a hard reset. Was not able to get output after xen says "Scrubbing > free memory.......Done." > > I'll keep testing for ya, as you release them. :-) I'm also seeing this same problem with my freshly built rebase/master i686 PAE kernel. I've sent the OOPS/backtrace to Jeremy, let's see what he has to say about it.. -- Pasi From rjones at redhat.com Tue Jul 14 14:25:11 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 14 Jul 2009 15:25:11 +0100 Subject: [fedora-virt] [ANNOUNCE] libguestfs 1.0.59 released Message-ID: <20090714142511.GB28327@amd.home.annexia.org> [This announcement covers version 1.0.58 too since it didn't get a separate message.] We are pleased to announce the release of libguestfs 1.0.59. Home page: http://libguestfs.org/ Downloads: http://libguestfs.org/download Git repo: http://git.et.redhat.com/?p=libguestfs.git;a=summary New in this release: - Support for Linux extended attributes. - Allow guestfish to be controlled remotely, so you can use one guestfish instance in a long-running shell script. - Support for reiserfs. - New function 'guestfs_zfile' -- 'file' inside compressed files. - New guestfish command 'reopen' -- reopen guestfish connection. - guestfish -x option (echo commands). - New function 'guestfs_version' to get the library version. - Many bugfixes and minor improvements: http://git.et.redhat.com/?p=libguestfs.git;a=log Thanks to Matthew Booth and Jon Fautley for their contributions and testing. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 75 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora From dlbewley at lib.ucdavis.edu Wed Jul 15 00:31:44 2009 From: dlbewley at lib.ucdavis.edu (Dale Bewley) Date: Tue, 14 Jul 2009 17:31:44 -0700 Subject: [fedora-virt] F12 virt features - what will or won't make it in? Message-ID: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> Following on the heals of John Poelstra, I was taking a look at all the F12 Virt Features with the release notes in mind. http://fedoraproject.org/wiki/Category:F12_Virt_Features That's an impressive and ambitious list! Given the schedule: 2009-07-28 Feature Freeze--Planning & Development Ends 2009-08-18 Alpha Release Identifying what is likely to actually make it will hopefully allow the release notes to be more focused and useful. I clicked through each and quickly came up with the categorized list below. I made a very quick uninformed guess at what was unlikely to make F12, otherwise I listed a feature as pending whether it is ready for the feature wrangler or not. If you know a feature is definitely not going to make it or if you think a feature is likely to make it out of pending status, please comment below or update the feature's targeted Fedora release. An evaluation of the percent complete or a bump to the last update date on the feature page might also be helpful. = Accepted = * http://fedoraproject.org/wiki/Features/VirtgPXE * http://fedoraproject.org/wiki/Features/VirtioSerial = Pending = * http://fedoraproject.org/wiki/Features/Hostinfo * http://fedoraproject.org/wiki/Features/KVM_Huge_Page_Backed_Memory * http://fedoraproject.org/wiki/Features/KVM_NIC_Hotplug * http://fedoraproject.org/wiki/Features/KVM_qcow2_Performance * http://fedoraproject.org/wiki/Features/libguestfs - : Technically, made it into F11, but... * http://fedoraproject.org/wiki/Features/SR-IOV * http://fedoraproject.org/wiki/Features/VHostNet * http://fedoraproject.org/wiki/Features/VirtTCK * http://fedoraproject.org/wiki/Features/VirtStorageManagement * http://fedoraproject.org/wiki/Features/Xen_to_KVM_migration = Unlikely? = * http://fedoraproject.org/wiki/Features/KSM * http://fedoraproject.org/wiki/Features/KVM_Stable_Guest_ABI * http://fedoraproject.org/wiki/Features/KVM_Stable_PCI_Addresses * http://fedoraproject.org/wiki/Features/Shared_Network_Interface * http://fedoraproject.org/wiki/Features/VirtAppliances * http://fedoraproject.org/wiki/Features/VirtAuthorization * http://fedoraproject.org/wiki/Features/VirtPrivileges * http://fedoraproject.org/wiki/Features/VirtVNCResourceTunnel * http://fedoraproject.org/wiki/Features/XenPvopsDom0 Thanks! -- Dale Bewley From berrange at redhat.com Wed Jul 15 09:13:37 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 15 Jul 2009 10:13:37 +0100 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> Message-ID: <20090715091337.GD28121@redhat.com> On Tue, Jul 14, 2009 at 05:31:44PM -0700, Dale Bewley wrote: > Following on the heals of John Poelstra, I was taking a look at all the > F12 Virt Features with the release notes in mind. > http://fedoraproject.org/wiki/Category:F12_Virt_Features > > That's an impressive and ambitious list! I'm feeling the pain trying to get it all done :-) > = Accepted = > * http://fedoraproject.org/wiki/Features/VirtgPXE > * http://fedoraproject.org/wiki/Features/VirtioSerial > > = Pending = > * http://fedoraproject.org/wiki/Features/Hostinfo > * http://fedoraproject.org/wiki/Features/KVM_Huge_Page_Backed_Memory > * http://fedoraproject.org/wiki/Features/KVM_NIC_Hotplug > * http://fedoraproject.org/wiki/Features/KVM_qcow2_Performance > * http://fedoraproject.org/wiki/Features/libguestfs - > : Technically, made it into F11, but... > * http://fedoraproject.org/wiki/Features/SR-IOV Essentially all there in rawhide already > * http://fedoraproject.org/wiki/Features/VHostNet > * http://fedoraproject.org/wiki/Features/VirtTCK Definitely get this > * http://fedoraproject.org/wiki/Features/VirtStorageManagement Yep, have most of this in current libvirt in rawhide > * http://fedoraproject.org/wiki/Features/Xen_to_KVM_migration > > = Unlikely? = > * http://fedoraproject.org/wiki/Features/KSM > * http://fedoraproject.org/wiki/Features/KVM_Stable_Guest_ABI > * http://fedoraproject.org/wiki/Features/KVM_Stable_PCI_Addresses These 3 are questions for Mark M ... > * http://fedoraproject.org/wiki/Features/Shared_Network_Interface Definltey get this > * http://fedoraproject.org/wiki/Features/VirtAppliances This one is questionable at this stage. > * http://fedoraproject.org/wiki/Features/VirtAuthorization Very unlikely, will shift to F13 > * http://fedoraproject.org/wiki/Features/VirtPrivileges Must have. > * http://fedoraproject.org/wiki/Features/VirtVNCResourceTunnel Will only be partially done. Likely dropping serial-over-VNC in favour of a plan b, todo serial-over-libvirt > * http://fedoraproject.org/wiki/Features/XenPvopsDom0 Unlikely due to ongoing upstream kenrel work Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From markmc at redhat.com Wed Jul 15 09:30:47 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 10:30:47 +0100 Subject: [fedora-virt] kvm/qemu network problem In-Reply-To: <4A574FDB.7080106@gmail.com> References: <4A574FDB.7080106@gmail.com> Message-ID: <1247650247.2860.58.camel@blaa> On Fri, 2009-07-10 at 10:27 -0400, Bret Rusnak wrote: > In installed win xp and everything installed fine, however my virtual > network card is not getting an ip address from my router. It is showing > up as a realtek RTL 8139 network card and is showing that the device is > working properly. That should work fine. Have you tried a Fedora guest, does it work? What is the part of "virsh dumpxml "? What's in /var/log/libvirt/qemu/.log See here for more useful information you could provide to help diagnose the issue: https://fedoraproject.org/wiki/Reporting_virtualization_bugs Cheers, Mark. From markmc at redhat.com Wed Jul 15 09:34:01 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 10:34:01 +0100 Subject: [fedora-virt] KVM update available? In-Reply-To: <4A5919BC.70800@gmail.com> References: <4A5919BC.70800@gmail.com> Message-ID: <1247650441.2860.60.camel@blaa> On Sat, 2009-07-11 at 19:01 -0400, Paul Lambert wrote: > On the SourceForge page there is a new Fedora KVM release 87 available. Which sourceforge page? kvm-87 is a development snapshot, it is available in rawhide. We will ship 0.11 in Fedora 12. > No date, no version. > > When I open add/remove software under Gnome (Fedora 11) I find that I > have QEMU system emulator x86-2:0.10.5-3.fc11 installed and > x86-2:0.10-16.fc11 available. This looks like a newer verion but how to > I know? There is no release date or release version shown in the lower > right pane where the package information is shown. Additionally, the > 10.5-3 versus 10-16 versioning makes me hesitate since I am not sure > these are one in the same package. 0.10.5 is newer than 0.10 Cheers, Mark. From markmc at redhat.com Wed Jul 15 09:39:07 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 10:39:07 +0100 Subject: [fedora-virt] cannot mount USB disks even after selinux update for Windows VM In-Reply-To: References: Message-ID: <1247650747.2860.64.camel@blaa> On Sun, 2009-07-12 at 11:35 -0400, Paul Lambert wrote: > LC_ALL=C PATH=/sbin:/usr/sbin:/bin:/usr/bin /usr/bin/qemu-kvm -S -M pc -m 768 -s > mp 2 -name Windows-XP-SP3-Home -uuid ee3bc9fe-a724-45b5-b675-11251f5c453f -monit > or pty -pidfile /var/run/libvirt/qemu//Windows-XP-SP3-Home.pid -boot c -drive fi > le=/var/lib/libvirt/images/Windows-XP-SP3-Home.img,if=ide,index=0,boot=on -drive > file=,if=ide,media=cdrom,index=2 -net nic,macaddr=54:52:00:7e:1c:92,vlan=0,mode > l=virtio -net tap,fd=17,vlan=0 -serial pty -parallel none -usb -usbdevice tablet > -vnc 127.0.0.1:0 -usbdevice host:1d6b:0002 > char device redirected to /dev/pts/0 > char device redirected to /dev/pts/1 > husb: open device 2.1 > husb: config #1 need -1 > husb: 1 interfaces claimed for configuration 1 > husb: grabbed usb device 2.1 > usb_linux_update_endp_table: Broken pipe > Warning: could not add USB device host:1d6b:0002 That looks like a bug. Try capturing the output of: $> strace -f -ttt qemu-kvm -M pc -m 768 -smp 2 -drive file=/var/lib/libvirt/images/Windows-XP-SP3-Home.img -net nic,macaddr=54:52:00:7e:1c:92,model=virtio -net user -serial pty -parallel none -usb -usbdevice tablet -vnc 127.0.0.1:0 -usbdevice host:1d6b:0002 -monitor stdio > t.log 2>&1 Cheers, Mark. From markmc at redhat.com Wed Jul 15 10:03:29 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 11:03:29 +0100 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> Message-ID: <1247652209.2860.88.camel@blaa> Hey, Feature owners, please read through the list below for your feature and: a) reply with a brief status update if I got it wrong b) make sure the feature page is up to date with the latest status c) if there is a reasonable chance of your feature making Fedora 12, make sure the page is complete and in the ReadyForWrangler category. It needs to be reviewed by FESCo this week or next. d) if it looks like it won't make Fedora 12, move it to the F-13 virt features category On Tue, 2009-07-14 at 17:31 -0700, Dale Bewley wrote: > Following on the heals of John Poelstra, I was taking a look at all the > F12 Virt Features with the release notes in mind. > http://fedoraproject.org/wiki/Category:F12_Virt_Features > > That's an impressive and ambitious list! > > Given the schedule: > 2009-07-28 Feature Freeze--Planning & Development Ends > 2009-08-18 Alpha Release > > Identifying what is likely to actually make it will hopefully allow the > release notes to be more focused and useful. I clicked through each and > quickly came up with the categorized list below. > > I made a very quick uninformed guess at what was unlikely to make F12, > otherwise I listed a feature as pending whether it is ready for the > feature wrangler or not. Thanks for doing this, my take on them all below. > If you know a feature is definitely not going to make it or if you think > a feature is likely to make it out of pending status, please comment > below or update the feature's targeted Fedora release. > > An evaluation of the percent complete or a bump to the last update date > on the feature page might also be helpful. > > = Accepted = > * http://fedoraproject.org/wiki/Features/VirtgPXE Done. > * http://fedoraproject.org/wiki/Features/VirtioSerial Ambitious for F-12 - e.g. needs some yet unaccepted upstream kernel patches to be backported. > = Pending = > * http://fedoraproject.org/wiki/Features/Hostinfo A little ambitious for Fedora 12, although AFAIK Rich is working hard on it. Also, once a first version has been cooked up, it should make it into Fedora very quickly. > * http://fedoraproject.org/wiki/Features/KVM_Huge_Page_Backed_Memory No real progress on this, and it's a long-standing issue. Most obviously missing is any progress on the libvirt side. I can't see this making Fedora 12. > * http://fedoraproject.org/wiki/Features/KVM_NIC_Hotplug Should make Fedora 12. The qemu bits are upstream now, and I hope to post the libvirt bits this week. > * http://fedoraproject.org/wiki/Features/KVM_qcow2_Performance AFAICT, it's pretty much done upstream - so the feature page just needs updating and moving into the ReadyForWrangler category. > * http://fedoraproject.org/wiki/Features/libguestfs - > : Technically, made it into F11, but... Yeah, it's done - it's just a matter of pimping it for Fedora 12. > * http://fedoraproject.org/wiki/Features/SR-IOV Done, just needs some testing details fleshed out. > * http://fedoraproject.org/wiki/Features/VHostNet Very ambitious for Fedora 12. Most obvious blocker is acceptance into the upstream kernel before backporting. I don't expect this to make it. > * http://fedoraproject.org/wiki/Features/VirtTCK My understanding is that this should not be difficult to get finished, but the feature page hasn't been updated in a while and I haven't seen any progress. > * http://fedoraproject.org/wiki/Features/VirtStorageManagement Haven't been following too closely, but I think this is more or less complete upstream. The feature page needs updating and moving to the ReadyForWrangler category. > * http://fedoraproject.org/wiki/Features/Xen_to_KVM_migration Not sure on the status here. Rich and Mat are working hard on it, but will it make F-12? > = Unlikely? = > * http://fedoraproject.org/wiki/Features/KSM Pending upstream finalizing the userland API before backporting it to the F-12 kernel. Not sure if there has been any progress on that in the last couple of weeks. If that was resolved, the feature should be quite straightforward to complete. > * http://fedoraproject.org/wiki/Features/KVM_Stable_Guest_ABI Some of the needed pieces are upstream in qemu now - i.e. using machine types for backwards compat. Still need a couple more changes to qemu here and then for libvirt to use it. Possible, but not certain, for Fedora 12. > * http://fedoraproject.org/wiki/Features/KVM_Stable_PCI_Addresses I think a lot of the qemu side is now upstream. It's mainly a question of whether Fedora 12 libvirt will be able to use it. > * http://fedoraproject.org/wiki/Features/Shared_Network_Interface I think this is largely done, but the feature page hasn't been updated in a long time. > * http://fedoraproject.org/wiki/Features/VirtAppliances Haven't seen any progress on this, probably won't make it in time. > * http://fedoraproject.org/wiki/Features/VirtAuthorization Haven't seen any progress on this, probably won't make it in time. > * http://fedoraproject.org/wiki/Features/VirtPrivileges Dan has some of this done, it may be a case that we limit the feature's scope for Fedora 12. > * http://fedoraproject.org/wiki/Features/VirtVNCResourceTunnel Dan has done some of the work here, but I've lost track of how likely it is to be complete for Fedora 12. > * http://fedoraproject.org/wiki/Features/XenPvopsDom0 Moved to F-13. Status still depends on upstream acceptance of the kernel patches, which is an ongoing saga. Thanks, Mark. From markmc at redhat.com Wed Jul 15 10:35:22 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 11:35:22 +0100 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <20090715091337.GD28121@redhat.com> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <20090715091337.GD28121@redhat.com> Message-ID: <1247654122.2860.97.camel@blaa> On Wed, 2009-07-15 at 10:13 +0100, Daniel P. Berrange wrote: > On Tue, Jul 14, 2009 at 05:31:44PM -0700, Dale Bewley wrote: > > * http://fedoraproject.org/wiki/Features/VirtTCK > > Definitely get this Move to ReadyForWrangler ? > > * http://fedoraproject.org/wiki/Features/VirtAppliances > > This one is questionable at this stage. Moved to f13. We can move it back if something changes. > > * http://fedoraproject.org/wiki/Features/VirtAuthorization > > Very unlikely, will shift to F13 Okay, I moved it. > > * http://fedoraproject.org/wiki/Features/VirtPrivileges > > Must have. Move to ReadyForWrangler? Probably needs a bit of cleanup to show just the bits we're doing for F-12 > > * http://fedoraproject.org/wiki/Features/VirtVNCResourceTunnel > > Will only be partially done. Likely dropping serial-over-VNC in favour > of a plan b, todo serial-over-libvirt Page needs updating. Cheers, Mark. From rjones at redhat.com Wed Jul 15 10:51:57 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Wed, 15 Jul 2009 11:51:57 +0100 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247652209.2860.88.camel@blaa> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <1247652209.2860.88.camel@blaa> Message-ID: <20090715105157.GF20648@amd.home.annexia.org> On Wed, Jul 15, 2009 at 11:03:29AM +0100, Mark McLoughlin wrote: > > = Pending = > > * http://fedoraproject.org/wiki/Features/Hostinfo > > A little ambitious for Fedora 12, although AFAIK Rich is working hard on > it. Also, once a first version has been cooked up, it should make it > into Fedora very quickly. Should have a reasonable chance of making it for F-12. > > * http://fedoraproject.org/wiki/Features/Xen_to_KVM_migration > > Not sure on the status here. Rich and Mat are working hard on it, but > will it make F-12? Should have something (RHEL migrations at least) by end of this week. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rich at lat.com Wed Jul 15 14:12:16 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 15 Jul 2009 10:12:16 -0400 Subject: [fedora-virt] Virtual Disk Setup Message-ID: <200907151412.n6FECGdX015099@raspberry.lat.com> I am setting up several VMs using an F11 host. Most of the VMs will be F11 as well. >From earlier discussions on this list I recognize that the best performance for virtual disks is with the backing storage on the host being a parititon or LV. Since I want some flexibility I will use LVs, with virtio disks on most of the VMs. Here's my questions: 1. Each f11 VM needs three file systems--/boot, root, and swap (assuming you can call swap a file system). Is it better to create three LVs (each) on the hosts, and treat it as three separate disks on the VMs? Or is it better to just create one LV on the host and then divide up that virtual disk on the VM? 2. Do I get better performance/stability by NOT using lvm on the VMs? In other words, just partition the virtio disk and create filesystems directly on the partitions? Or do the wonders of LVM and virtio already build in any advantage that might give? 3. Do I get the best performance/stability by creating an LV for each disk I need, and then NOT partitioning it on the VM, but using the whole disk for a file system. In other words, use vda, not vda1, vda2, etc for the filesystem. This would give the side effect being able to easily mount the filesystem on the host machine when the VM wasn't being run. 4. Lastly (for now) are these issues too miniscule in their effects that I probably shouldn't even be worrying about them? Thanks for all the help. Rich From berrange at redhat.com Wed Jul 15 14:21:15 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Wed, 15 Jul 2009 15:21:15 +0100 Subject: [fedora-virt] Virtual Disk Setup In-Reply-To: <200907151412.n6FECGdX015099@raspberry.lat.com> References: <200907151412.n6FECGdX015099@raspberry.lat.com> Message-ID: <20090715142115.GN28121@redhat.com> On Wed, Jul 15, 2009 at 10:12:16AM -0400, Rich Mahn wrote: > I am setting up several VMs using an F11 host. Most of the VMs will > be F11 as well. > > >From earlier discussions on this list I recognize that the best > performance for virtual disks is with the backing storage on the host > being a parititon or LV. Since I want some flexibility I will use > LVs, with virtio disks on most of the VMs. > > Here's my questions: > > 1. Each f11 VM needs three file systems--/boot, root, and swap > (assuming you can call swap a file system). Is it better to create > three LVs (each) on the hosts, and treat it as three separate disks > on the VMs? Or is it better to just create one LV on the host and > then divide up that virtual disk on the VM? There's no point separating /boot & root onto separate virtual disks. You could argue there's a possible advatnage in having swap separate if you expect to use swap in the guest, and you have separate disk spindles in the host you could dedicate to the guest' swap disk. To be honest though this is niche benefit at best. THe only separation I'd do is for the OS system disks, vs application data disks (or /home if you intended to store lots of data there). this makes it easier to upgrade OS - eg provision a new OS with the latest disto, and then just move your data disk to the new guest , and throw away the old guest. > > 2. Do I get better performance/stability by NOT using lvm on the VMs? > In other words, just partition the virtio disk and create > filesystems directly on the partitions? Or do the wonders of LVM > and virtio already build in any advantage that might give? LVM makes is easier to resize guest FS. eg add a second disk to the guest, format it as a LVM PV and add it to your VG. That's pretty much only wayto add more capacity on a running guest. > > 3. Do I get the best performance/stability by creating an LV for each > disk I need, and then NOT partitioning it on the VM, but using the > whole disk for a file system. In other words, use vda, not vda1, > vda2, etc for the filesystem. This would give the side effect > being able to easily mount the filesystem on the host machine when > the VM wasn't being run. Anaconda will refuse to install onto a raw disk, it mandates partitioning. Second point is that not using a partition table can cause unexpected problems - eg vgscan in the host may accidentally see & activate stuff from your guests' disks with predictable goodbye-data results if your guest is active. > 4. Lastly (for now) are these issues too miniscule in their effects > that I probably shouldn't even be worrying about them? That's certainly my opinion. Sure you get some performance but you loose the great administrative flexibility of LVM. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From markmc at redhat.com Wed Jul 15 14:39:48 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 15 Jul 2009 15:39:48 +0100 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247665111.3773.3.camel@localhost.localdomain> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <1247652209.2860.88.camel@blaa> <1247665111.3773.3.camel@localhost.localdomain> Message-ID: <1247668788.2860.113.camel@blaa> On Wed, 2009-07-15 at 08:38 -0500, Justin M. Forbes wrote: > On Wed, 2009-07-15 at 11:03 +0100, Mark McLoughlin wrote: > > > = Unlikely? = > > > * http://fedoraproject.org/wiki/Features/KSM > > > > Pending upstream finalizing the userland API before backporting it to > > the F-12 kernel. Not sure if there has been any progress on that in the > > last couple of weeks. If that was resolved, the feature should be quite > > straightforward to complete. > > > Actually quite likely to make F12. There was an madvise based API rollup > at the end of June, and after a bit of back and forth, it appears that > it is ready to push upstream as of this week. I am trying to catch Izik > today for some final clarification before pushing the fedora kernel > piece. I will update the feature page this week once I have the > clarification I need on details. Cool. In that case, you should move it to the ReadyForWrangler category so it can get on the list for this weeks FESCo meeting. Cheers, Mark. From gianluca.cecchi at gmail.com Wed Jul 15 15:05:40 2009 From: gianluca.cecchi at gmail.com (Gianluca Cecchi) Date: Wed, 15 Jul 2009 17:05:40 +0200 Subject: [fedora-virt] fence_xvm and qemu/kvm problem Message-ID: <561c252c0907150805m4385481es2a17d772e9f2a018@mail.gmail.com> Hello, I'm testing this: host = Fedora 11 x86_64 using Qemu/Kvm as virtualization specs on sw versions: libvirt-0.6.2-12.fc11.x86_64 qemu-common-0.10.5-3.fc11.x86_64 qemu-kvm-0.10.5-3.fc11.x86_64 qemu-system-x86-0.10.5-3.fc11.x86_64 qemu-img-0.10.5-3.fc11.x86_64 cman-3.0.0-15.rc1.fc11.x86_64 two guests = CentOS 5.3 x86_64 with cluster suite installed and configured with almost latest packages specs on sw versions: cman-2.0.98-1.el5_3.1 openais-0.80.3-22.el5_3.4 rgmanager-2.0.46-1.el5.centos.3 kernel-2.6.18-128.1.10.el5 the cluster itself works well in preliminary tests (I have quorum disk and one heuristic pinging to the qemu/kvm host as a gateway): poweroff and automatic relocation, manual relocation with clusvcadm, HALVM, ecc. I registered one problem though, that could lead to data corruption or other unintended effects in my opinion. I configured fence_xvm agent on the guests. At the moment the host is a standalone one. I read (bugzilla https://bugzilla.redhat.com/show_bug.cgi?id=362351) that I can manage this configuration using on the host side the standalone command fence_xvmd -LX (installing cman and dependencies, but actually not running it as a service) My guests use virbr0 as the prod lan and virbr1 as rhe intracluster one, and I noticed that I had to issue actually this command to keep alive the daemon on host side: fence_xvmd -dLX -i ipv4 -I virbr0 -U qemu:///system (probably the key part is the -I virbr0 option) Otherwise I get: Jul 15 11:54:04 virtfed xvmd[606]: Could not set up multicast listen socket Configuring the fence daemon, at first I was wrong configuring the "domain=" part In fact initially I put in the node name (node1), instead of the domain name of the guest inside the qemu/kvm HV..... This error gave me the opportunity to detect a wrong behaviour in my combination. If I put node name and issue this command from node2: fence_xvm -H node1 I get: Remote: operation was successful but actually the guest is not fenced at all. The qemu/kvm host /var/log/messages contains: Jul 15 12:17:21 virtfed libvirtd: 12:17:21.566: error : Domain not found Jul 15 12:17:21 virtfed xvmd[658]: Rebooting domain node1... Jul 15 12:17:21 virtfed libvirtd: 12:17:21.574: error : Domain not found Jul 15 12:17:21 virtfed xvmd[658]: Failed to connect to caller: Bad file descriptor Instead, when using the correct domain name part: fence_xvm -H centos53 I again get Remote: operation was successful and the guest is really fenced (rebooted by default) In qemu/kvm host logs I get now: Jul 15 12:18:31 virtfed xvmd[658]: Rebooting domain centos53... Jul 15 12:18:31 virtfed kernel: virbr0: port 2(vnet2) entering disabled state Jul 15 12:18:31 virtfed kernel: device vnet2 left promiscuous mode Jul 15 12:18:31 virtfed kernel: virbr0: port 2(vnet2) entering disabled state Jul 15 12:18:31 virtfed kernel: virbr1: port 2(vnet3) entering disabled state Jul 15 12:18:31 virtfed kernel: device vnet3 left promiscuous mode Jul 15 12:18:31 virtfed kernel: virbr1: port 2(vnet3) entering disabled state Jul 15 12:18:32 virtfed libvirtd: 12:18:32.245: error : operation failed: domain 'centos53' is already defined Jul 15 12:18:32 virtfed kernel: device vnet2 entered promiscuous mode Jul 15 12:18:32 virtfed kernel: virbr0: topology change detected, propagating Jul 15 12:18:32 virtfed kernel: virbr0: port 2(vnet2) entering forwarding state Jul 15 12:18:32 virtfed kernel: device vnet3 entered promiscuous mode Jul 15 12:18:32 virtfed kernel: virbr1: topology change detected, propagating Jul 15 12:18:32 virtfed kernel: virbr1: port 2(vnet3) entering forwarding state Jul 15 12:18:33 virtfed xvmd[658]: Failed to connect to caller: Bad file descriptor Is it my configuration (F11 host with cman part based on 3.0 and centos53 guests with 2.98 cman part) supposed to work? In this case where to bugzilla? Thanks in advance, Gianluca From rich at lat.com Wed Jul 15 15:34:25 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 15 Jul 2009 11:34:25 -0400 Subject: [fedora-virt] Virtual Disk Setup In-Reply-To: Your message of "Wed, 15 Jul 2009 15:21:15 BST." <20090715142115.GN28121@redhat.com> Message-ID: <200907151534.n6FFYPV8020395@raspberry.lat.com> On Wed, Jul 15, 2009 at 10:12:16AM -0400, Rich Mahn wrote: > I am setting up several VMs using an F11 host. Most of the VMs will > be F11 as well. > > >From earlier discussions on this list I recognize that the best > performance for virtual disks is with the backing storage on the host > being a parititon or LV. Since I want some flexibility I will use > LVs, with virtio disks on most of the VMs. > > Here's my questions: > > 1. Each f11 VM needs three file systems--/boot, root, and swap > (assuming you can call swap a file system). Is it better to create > three LVs (each) on the hosts, and treat it as three separate disks > on the VMs? Or is it better to just create one LV on the host and > then divide up that virtual disk on the VM? There's no point separating /boot & root onto separate virtual disks. You could argue there's a possible advatnage in having swap separate if you expect to use swap in the guest, and you have separate disk spindles in the host you could dedicate to the guest' swap disk. To be honest though this is niche benefit at best. THe only separation I'd do is for the OS system disks, vs application data disks (or /home if you intended to store lots of data there). this makes it easier to upgrade OS - eg provision a new OS with the latest disto, and then just move your data disk to the new guest , and throw away the old guest. > > 2. Do I get better performance/stability by NOT using lvm on the VMs? > In other words, just partition the virtio disk and create > filesystems directly on the partitions? Or do the wonders of LVM > and virtio already build in any advantage that might give? LVM makes is easier to resize guest FS. eg add a second disk to the guest, format it as a LVM PV and add it to your VG. That's pretty much only wayto add more capacity on a running guest. > > 3. Do I get the best performance/stability by creating an LV for each > disk I need, and then NOT partitioning it on the VM, but using the > whole disk for a file system. In other words, use vda, not vda1, > vda2, etc for the filesystem. This would give the side effect > being able to easily mount the filesystem on the host machine when > the VM wasn't being run. Anaconda will refuse to install onto a raw disk, it mandates partitioning. Second point is that not using a partition table can cause unexpected problems - eg vgscan in the host may accidentally see & activate stuff from your guests' disks with predictable goodbye-data results if your guest is active. > 4. Lastly (for now) are these issues too miniscule in their effects > that I probably shouldn't even be worrying about them? That's certainly my opinion. Sure you get some performance but you loose the great administrative flexibility of LVM. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From rich at lat.com Wed Jul 15 15:56:56 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 15 Jul 2009 11:56:56 -0400 Subject: [fedora-virt] Virtual Disk Setup In-Reply-To: Your message of "Wed, 15 Jul 2009 15:21:15 BST." <20090715142115.GN28121@redhat.com> Message-ID: <200907151556.n6FFuuGi021581@raspberry.lat.com> ==== > > 1. Each f11 VM needs three file systems--/boot, root, and swap > > (assuming you can call swap a file system). Is it better to create > > three LVs (each) on the hosts, and treat it as three separate disks > > on the VMs? Or is it better to just create one LV on the host and > > then divide up that virtual disk on the VM? > > There's no point separating /boot & root onto separate virtual > disks. You could argue there's a possible advatnage in having > swap separate if you expect to use swap in the guest, and you > have separate disk spindles in the host you could dedicate to > the guest' swap disk. To be honest though this is niche benefit > at best. > > THe only separation I'd do is for the OS system disks, vs application > data disks (or /home if you intended to store lots of data there). > this makes it easier to upgrade OS - eg provision a new OS with the > latest disto, and then just move your data disk to the new guest , > and throw away the old guest. Yes. I planned on doing a bit of this anyhow. Testing some applications under different configuration and the like. > > 2. Do I get better performance/stability by NOT using lvm on the VMs? > > In other words, just partition the virtio disk and create > > filesystems directly on the partitions? Or do the wonders of LVM > > and virtio already build in any advantage that might give? > > LVM makes is easier to resize guest FS. eg add a second disk > to the guest, format it as a LVM PV and add it to your VG. > That's pretty much only wayto add more capacity on a running > guest. I hadn't thought about that. With abundant disk space on the host, I can also make the second disk large enough to migrate the first PV on the VM to the second, remove the first pv, and then still only use one LV from the host. ==== > > 4. Lastly (for now) are these issues too miniscule in their effects > > that I probably shouldn't even be worrying about them? > > That's certainly my opinion. Sure you get some performance > but you loose the great administrative flexibility of LVM. > > Daniel Sounds good. Thanks for your help. Rich From rich at lat.com Wed Jul 15 16:42:46 2009 From: rich at lat.com (Rich Mahn) Date: Wed, 15 Jul 2009 12:42:46 -0400 Subject: [fedora-virt] Virtual Disk Setup In-Reply-To: Your message of "Wed, 15 Jul 2009 11:34:25 EDT." <200907151534.n6FFYPV8020395@raspberry.lat.com> Message-ID: <200907151642.n6FGgkjE024393@raspberry.lat.com> ----snip snip ---- AARRGGHH. Sorry about the duplicate. Hit the wrong escape-meta-alt-control-shift keys when trying to reply. -- rich From lutter at redhat.com Wed Jul 15 17:17:58 2009 From: lutter at redhat.com (David Lutterkort) Date: Wed, 15 Jul 2009 10:17:58 -0700 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247652209.2860.88.camel@blaa> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <1247652209.2860.88.camel@blaa> Message-ID: <1247678278.7925.258.camel@avon.watzmann.net> On Wed, 2009-07-15 at 11:03 +0100, Mark McLoughlin wrote: > > * http://fedoraproject.org/wiki/Features/Shared_Network_Interface > > I think this is largely done, but the feature page hasn't been updated > in a long time. I will do that today, and try and get it on FESCo's agenda for this Friday. David From wildfire at progsoc.org Wed Jul 15 17:23:34 2009 From: wildfire at progsoc.org (Anand Kumria) Date: Wed, 15 Jul 2009 18:23:34 +0100 Subject: [fedora-virt] Virtual Disk Setup In-Reply-To: <20090715142115.GN28121@redhat.com> References: <200907151412.n6FECGdX015099@raspberry.lat.com> <20090715142115.GN28121@redhat.com> Message-ID: <971f65790907151023h8208b53g73efc0de9a3f14b9@mail.gmail.com> On Wed, Jul 15, 2009 at 3:21 PM, Daniel P. Berrange wrote: > On Wed, Jul 15, 2009 at 10:12:16AM -0400, Rich Mahn wrote: > > I am setting up several VMs using an F11 host. Most of the VMs will > > be F11 as well. > > > > >From earlier discussions on this list I recognize that the best > > performance for virtual disks is with the backing storage on the host > > being a parititon or LV. Since I want some flexibility I will use > > LVs, with virtio disks on most of the VMs. > > > > Here's my questions: > > > > 1. Each f11 VM needs three file systems--/boot, root, and swap > > (assuming you can call swap a file system). Is it better to create > > three LVs (each) on the hosts, and treat it as three separate disks > > on the VMs? Or is it better to just create one LV on the host and > > then divide up that virtual disk on the VM? > > There's no point separating /boot & root onto separate virtual > disks. Really? I have to admit to only being familiar with Xen, so I do not know if this also applies to KVM-style virtualisation. What I have found is that if you use pygrub (a minimal implementation of grub written in Python) and attempt to boot a domain, it will have issues unless /boot is a file. Which has mean that I have made it separate to /, an LVM VG - for the reasons you suggest. Also - within the guest it wants to have a partition table and Xen, at least, will simply have the devices /dev/sda1 and /dev/sda2 but not /dev/sda which means grub (in the guest) complains. Having /boot on a file based disk, with a parition table at the front, means that /dev/sda is provided and that the guest is able to run grub without hacking the device-map file (or temporarily make the device node, since it will show up). So, I'm one of "those people" looking to eventually migrate from Xen to KVM -- is this issue all taken care of by KVM-style virtualisation? Regards, Anand -------------- next part -------------- An HTML attachment was scrubbed... URL: From eb30750 at gmail.com Thu Jul 16 03:45:28 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Wed, 15 Jul 2009 23:45:28 -0400 Subject: [fedora-virt] Win slave disk not booting Message-ID: I create a second bootable disk on my Win guest. I then copy my existing boot disk to the new disk with a Win track for track copy program. I when remove the existing boot disk and attempt to boot the Win vm with the new bootable disk the boot program returns an error that it can't find boot information. Essentially I am using the same technique with software disks that I do when replacing physical hard drives. Install the new disk in an external USB enclosure and perform the track for track copy then install the new disk as the boot disk. Works everytime. Why won't this work in a virtual guest? I am doing this to reduce the size of my disk space. There's most likely a virt command line utility but the GUI program should work too. The only thing different I notice is that the second disk is being configured as a bootable slave. Updated several bugs with new findings. PJAL -------------- next part -------------- An HTML attachment was scrubbed... URL: From cjohnstonwork at gmail.com Tue Jul 7 14:58:32 2009 From: cjohnstonwork at gmail.com (Christopher Johnston) Date: Tue, 7 Jul 2009 10:58:32 -0400 Subject: [fedora-virt] Re: febootstrap question In-Reply-To: <20090619225723.GB15252@amd.home.annexia.org> References: <63aeb0300906171425l3da1156aydc9b7a649e4ce00d@mail.gmail.com> <20090617213802.GA3309@amd.home.annexia.org> <63aeb0300906191444r353d2242x6bf3385e728f177c@mail.gmail.com> <20090619225723.GB15252@amd.home.annexia.org> Message-ID: <63aeb0300907070758x1d9a1899y23067c006d33b4b5@mail.gmail.com> Rich, Wanted to updated you on what I was working on using febootstrap. I managed to get a fully booted F10 system that can be PXE booted and pivot the rootfs filesystem into tmpfs. It then forks init off to start the usual boot process. Very happy so far with how it is coming along with the project. The source of the problem turned out to be the upx binary minimize process, once I disabled that it worked great. I am running into another smaller issue where the rpmdb gets corrupted after the system boots. I am also not running the minimizer to remove the rpmdb as I need this at boot time when the system is up and running to install some required RPMs. Here is the chroot environment for the image, strangely rpm -qa doesnt report anything yet the files are all in tack (strings Packages even shows data). Have you seen this where the rpmdb gets corrupted at boot time? CHROOT: [root at ns4 /]# cd /var/lib/rpm/ [root at ns4 rpm]# ls Basenames Dirnames Group Name Providename Pubkeys Requireversion Sigmd5 __db.000 __db.002 __db.004 Conflictname Filedigests Installtid Packages Provideversion Requirename Sha1header Triggername __db.001 __db.003 [root at ns4 rpm]# rm -f __db.00* [root at ns4 rpm]# rpm --rebuilddb [root at ns4 rpm]# rpm -qa [root at ns4 rpm]# ls -ltr total 5920 -rw-r--r-- 1 7103 users 12288 Jul 2 17:01 Pubkeys -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Conflictname -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Triggername -rw-r--r-- 1 7103 users 4526080 Jul 2 17:02 Packages -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Name -rw-r--r-- 1 7103 users 684032 Jul 2 17:02 Basenames -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Group -rw-r--r-- 1 7103 users 65536 Jul 2 17:02 Requirename -rw-r--r-- 1 7103 users 86016 Jul 2 17:02 Providename -rw-r--r-- 1 7103 users 118784 Jul 2 17:02 Dirnames -rw-r--r-- 1 7103 users 45056 Jul 2 17:02 Requireversion -rw-r--r-- 1 7103 users 32768 Jul 2 17:02 Provideversion -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Installtid -rw-r--r-- 1 7103 users 12288 Jul 2 17:02 Sigmd5 -rw-r--r-- 1 7103 users 24576 Jul 2 17:02 Sha1header -rw-r--r-- 1 7103 users 684032 Jul 2 17:02 Filedigests BOOTED SYSTEM: [root at core021 yum.repos.d]# rpm -qa rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9 error: cannot open Packages index using db3 - Invalid argument (22) error: cannot open Packages database in /var/lib/rpm rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9 error: cannot open Packages database in /var/lib/rpm On Fri, Jun 19, 2009 at 6:57 PM, Richard W.M. Jones wrote: > On Fri, Jun 19, 2009 at 05:44:52PM -0400, Christopher Johnston wrote: > > Now to get this going for my testing I am comfortable using rootfs > > (pivotroot and switchroot dont seem to work in nash). > > I'm a bit surprised about that, because obviously switchroot is used > all the time in mkinitrd-built initrds, eg. look at the following > lines in mkinitrd: > > emit "echo Switching to new root and running init." > emit "switchroot" > emit "echo Booting has failed." > emit "sleep -1" > > When you say dont seem to work, is there any diagnostic? > > > What I have done in my testing here is generate a linuxrc which I posted. > I > > attmpted to use bash instead of nash and have it just fork /sbin/init but > > that also did not work (upstarts init does not seem to work well here). > > > > I looked over the script you are using here for your virtual machine, but > > what are you actually doing to start init so the usual RC stuff can start > > running? > > Well in the init script we use, we _don't_ run any rc stuff. It's > just for a small appliance, so we set up what we need (ifconfig lo and > eth0), modprobe a few modules, and then run our daemon directly. > > Having said that, it should easily be possible to use febootstrap to > run the ordinary scripts, but the problem probably isn't febootstrap, > but some bug/difference/sensitivity in /init, nash, permissions etc. > > Is the upstart %post script failing? febootstrap runs all %post > scripts under fakeroot+fakechroot, and they can sometimes behave > differently. > > Are you booting these on real hardware? I suggest testing it under > qemu - it's much more controllable, and allows you to test things > faster. > > Rich. > > -- > Richard Jones, Emerging Technologies, Red Hat > http://et.redhat.com/~rjones > Read my programming blog: http://rwmj.wordpress.com > Fedora now supports 75 OCaml packages (the OPEN alternative to F#) > http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jforbes at redhat.com Wed Jul 15 13:38:31 2009 From: jforbes at redhat.com (Justin M. Forbes) Date: Wed, 15 Jul 2009 08:38:31 -0500 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247652209.2860.88.camel@blaa> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <1247652209.2860.88.camel@blaa> Message-ID: <1247665111.3773.3.camel@localhost.localdomain> On Wed, 2009-07-15 at 11:03 +0100, Mark McLoughlin wrote: > > = Unlikely? = > > * http://fedoraproject.org/wiki/Features/KSM > > Pending upstream finalizing the userland API before backporting it to > the F-12 kernel. Not sure if there has been any progress on that in the > last couple of weeks. If that was resolved, the feature should be quite > straightforward to complete. > Actually quite likely to make F12. There was an madvise based API rollup at the end of June, and after a bit of back and forth, it appears that it is ready to push upstream as of this week. I am trying to catch Izik today for some final clarification before pushing the fedora kernel piece. I will update the feature page this week once I have the clarification I need on details. Justin From dallan at redhat.com Wed Jul 15 20:26:54 2009 From: dallan at redhat.com (Dave Allan) Date: Wed, 15 Jul 2009 16:26:54 -0400 Subject: [fedora-virt] F12 virt features - what will or won't make it in? In-Reply-To: <1247652209.2860.88.camel@blaa> References: <1247617904.9691.36.camel@tofu.lib.ucdavis.edu> <1247652209.2860.88.camel@blaa> Message-ID: <4A5E3B8E.106@redhat.com> Mark McLoughlin wrote: >> * http://fedoraproject.org/wiki/Features/VirtStorageManagement > > Haven't been following too closely, but I think this is more or less > complete upstream. The feature page needs updating and moving to the > ReadyForWrangler category. 2/3 complete upstream. Multipath remains to be done. I'll update the feature page shortly. Dave From rpjday at crashcourse.ca Thu Jul 16 10:14:42 2009 From: rpjday at crashcourse.ca (Robert P. J. Day) Date: Thu, 16 Jul 2009 06:14:42 -0400 (EDT) Subject: [fedora-virt] do current virt packages work well with 2.6.31-rc3? Message-ID: for various reasons, i'm running my fully-updated f11 system with a 2.6.31-rc3 kernel, which i got by copying the current config file from /boot and running "make oldconfig". is there any reason that this won't work with the current fedora 11 virt packages? the only issue i'm having is with the radeon video driver that won't let me run in full 1280x800 but, other than that, all else looks good. is there any reason to think that virtualization will fail with this newer kernel? thanks. rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Annoying Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday "Kernel Newbie Corner" column @ linux.com: http://cli.gs/WG6WYX ======================================================================== From markmc at redhat.com Thu Jul 16 10:31:52 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Thu, 16 Jul 2009 11:31:52 +0100 Subject: [fedora-virt] do current virt packages work well with 2.6.31-rc3? In-Reply-To: References: Message-ID: <1247740312.3038.24.camel@blaa> On Thu, 2009-07-16 at 06:14 -0400, Robert P. J. Day wrote: > for various reasons, i'm running my fully-updated f11 system with a > 2.6.31-rc3 kernel, which i got by copying the current config file from > /boot and running "make oldconfig". is there any reason that this > won't work with the current fedora 11 virt packages? Short answer - nope, it should work fine. (And please file bugs if it doesn't) Cheers, Mark. From markmc at redhat.com Thu Jul 16 17:04:13 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Thu, 16 Jul 2009 18:04:13 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1246636154.13604.8.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> Message-ID: <1247763853.3038.105.camel@blaa> More qemu updates in the preview repo: * Thu Jul 16 2009 Mark McLoughlin - 2:0.10.50-11.kvm88 - Update to kvm-88, see http://www.linux-kvm.org/page/ChangeLog - Package mutiboot.bin - Update for how extboot is built - Fix sf.net source URL - Drop qemu-fix-ppc-softmmu-kvm-disabled-build.patch - Drop qemu-fix-pcspk-build-with-kvm-disabled.patch - Cherry-pick fix for esound support build failure * Wed Jul 15 2009 Daniel Berrange - 2:0.10.50-10.kvm87 - Add udev rules to make /dev/kvm world accessible & group=kvm (rhbz #497341) - Create a kvm group if it doesn't exist (rhbz #346151) * Tue Jul 07 2009 Glauber Costa - 2:0.10.50-9.kvm87 - use pxe roms from gpxe, instead of etherboot package. Cheers, Mark. From gene at czarc.net Thu Jul 16 18:22:08 2009 From: gene at czarc.net (Gene Czarcinski) Date: Thu, 16 Jul 2009 14:22:08 -0400 Subject: [fedora-virt] qemu question/clarification Message-ID: <200907161422.08410.gene@czarc.net> qemu documentation such as the man page for qemu-img says that only versions 3 and 4 for the vmdk files are supported. What does this mean? If I run "strings" on a vmdk (sparse file, single image), I get some text lines which appear to describe the virtual disk. One of these lines is: HWversion=n If I create a VMware guest under Workstation 6.5.2 and specify Workstation 4 compatibility, I get HWversion=3. If I specify Workstation 6.5.2 compatibility, then I get HWversion=7. I assume that HWversion=4 will be true for Workstation 5 compatibility but I have not tested that. Is this what is meant by "versions 3 and 4" compatibility by qemu? I have run qemu-img to convert various vmdk files and it does not complain about non HWversion=3 or HWversion=4 files. Furthermore, the converted files seem OK when examined by guestfish. Gene From m.a.young at durham.ac.uk Thu Jul 16 22:50:07 2009 From: m.a.young at durham.ac.uk (M A Young) Date: Thu, 16 Jul 2009 23:50:07 +0100 (BST) Subject: [fedora-virt] Re: [Fedora-xen] Dom0 kernels In-Reply-To: References: <20090328163545.GM31725@salstar.sk> <20090414143618.GH351@redhat.com> Message-ID: And another update (kernel-2.6.31-0.1.2.43.rc3..xendom0.fc12) at http://koji.fedoraproject.org/koji/taskinfo?taskID=1477549 and the repository http://fedorapeople.org/~myoung/dom0/ . There have been some acpi and xenbus patches, but i686 still doesn't work for me. Michael Young From markmc at redhat.com Fri Jul 17 10:28:50 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 17 Jul 2009 11:28:50 +0100 Subject: [fedora-virt] qemu question/clarification In-Reply-To: <200907161422.08410.gene@czarc.net> References: <200907161422.08410.gene@czarc.net> Message-ID: <1247826530.25020.42.camel@blaa> On Thu, 2009-07-16 at 14:22 -0400, Gene Czarcinski wrote: > qemu documentation such as the man page for qemu-img says that only versions 3 > and 4 for the vmdk files are supported. What does this mean? Try "hexdump -C -n 4" on the files - vmdk.c says: #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') #define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') Cheers, Mark. From needwork at gmail.com Sat Jul 18 02:47:23 2009 From: needwork at gmail.com (Lester M.) Date: Fri, 17 Jul 2009 22:47:23 -0400 Subject: [fedora-virt] Xenner, Ok, who has used it and can somebody provide a syntax example / real example? Message-ID: <2cc75dd80907171947s6df04b9by74659e9c36c8e74c@mail.gmail.com> Xenner, yes xenner... Ok, who has used it and can somebody provide a syntax example / real example? Did the google / yahoo / search, I would like to see an example, as well as hear of everyone's experiences using xenner, while we wait for a more stable native dom0 / upstream support for xen. Any takers? :-) -------------- next part -------------- An HTML attachment was scrubbed... URL: From gianluca.cecchi at gmail.com Mon Jul 20 08:45:56 2009 From: gianluca.cecchi at gmail.com (Gianluca Cecchi) Date: Mon, 20 Jul 2009 10:45:56 +0200 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts Message-ID: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> Hello, is there any pointer about how to set up a cluster of Qemu/KVM hosts? I'm on F11 x86_64 for the hosts. I read requirements for KVM migration in general highlighted at http://www.linux-kvm.org/page/Migration but I keep having doubts, in particular regarding libvirt configuration in cluster environments... Some questions about libvirt configuration: - /etc/libvirt/qemu/networks do the files inside here be identical between hosts (default.xml and other custom configured network ones)? What are the uuid tags into the xml for? Do they have to be identical for clusters or do they have to be absolutely different for a sort of "identification" of host (as the term seems to suggest)? If I have guests that use virbr0 and use dhcp for their network config, and want two different qemu/kvm hosts able to migrate these guests between them, need to have same config or what? - the same for storage configuration and other parameters. Suppose I clone a pre-config F11 host configured with libvirt, and suppose I have to differentiate uuid for networks/storage (see questions above), do I have a method to regenerate these uuid values inside xml files? Thanks in advance for any pointer. Gianluca From rjones at redhat.com Mon Jul 20 09:41:01 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 20 Jul 2009 10:41:01 +0100 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> Message-ID: <20090720094101.GB8751@amd.home.annexia.org> On Mon, Jul 20, 2009 at 10:45:56AM +0200, Gianluca Cecchi wrote: > Hello, > is there any pointer about how to set up a cluster of Qemu/KVM hosts? > I'm on F11 x86_64 for the hosts. I was going to answer this in detail, but I'm not really an expert on this. You may be better off looking at http://ovirt.org/, which is an open source management tool designed precisely for looking after networks of virt hosts. It is based on libvirt, and they have looked at and solved many of the issues you raise. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From dwight.hubbard at efausol.com Mon Jul 20 18:18:25 2009 From: dwight.hubbard at efausol.com (Dwight Hubbard) Date: Mon, 20 Jul 2009 11:18:25 -0700 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> Message-ID: <200907201118.26177.dwight.hubbard@efausol.com> The question I keep bumping into is where are the cluster resource scripts for libvirt or kvm virtual machines. Migration is nice, but it doesn't do much good in the event a server decides to up and die instead of going down cleanly... On Monday 20 July 2009 01:45:56 Gianluca Cecchi wrote: > Hello, > is there any pointer about how to set up a cluster of Qemu/KVM hosts? > I'm on F11 x86_64 for the hosts. > I read requirements for KVM migration in general highlighted at > http://www.linux-kvm.org/page/Migration but I keep having doubts, in > particular regarding libvirt configuration in cluster environments... > Some questions about libvirt configuration: > - /etc/libvirt/qemu/networks > do the files inside here be identical between hosts (default.xml and > other custom configured network ones)? > What are the uuid tags into the xml for? Do they have to be identical > for clusters or do they have to be absolutely different for a sort of > "identification" of host (as the term seems to suggest)? > If I have guests that use virbr0 and use dhcp for their network > config, and want two different qemu/kvm hosts able to migrate these > guests between them, need to have same config or what? > - the same for storage configuration and other parameters. > > Suppose I clone a pre-config F11 host configured with libvirt, and > suppose I have to differentiate uuid for networks/storage (see > questions above), do I have a method to regenerate these uuid values > inside xml files? > > Thanks in advance for any pointer. > Gianluca > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt -- -- -- Dwight Hubbard Principal Consultant Effective Automation Solutions Website: http://effectiveautomationsolutions.com Email: dwight.hubbard at efausol.com Phone: (503) 941-0327 Redhat Certified Engineer - RHCE #804007137224095 VMware Certified Professional - VCP #18529 -------------- next part -------------- An HTML attachment was scrubbed... URL: From rjones at redhat.com Thu Jul 23 09:06:53 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 23 Jul 2009 10:06:53 +0100 Subject: [fedora-virt] virt-what 1.1 released Message-ID: <20090723090653.GA32278@amd.home.annexia.org> I just released virt-what 1.1. This program is a collection of code snippets to allow you to determine what sort of virtualization you are running inside. The new version can tell the difference between QEMU and KVM, and can tell if you are running inside a Xen fullvirt guest. Home page: http://et.redhat.com/~rjones/virt-what/ Downloads: http://et.redhat.com/~rjones/virt-what/files/ Repository: http://git.et.redhat.com/?p=virt-what.git;a=summary Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Thu Jul 23 09:12:26 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 23 Jul 2009 10:12:26 +0100 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <200907201118.26177.dwight.hubbard@efausol.com> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> <200907201118.26177.dwight.hubbard@efausol.com> Message-ID: <20090723091226.GA32325@amd.home.annexia.org> On Mon, Jul 20, 2009 at 11:18:25AM -0700, Dwight Hubbard wrote: > The question I keep bumping into is where are the cluster resource scripts for > libvirt or kvm virtual machines. Migration is nice, but it doesn't do much > good in the event a server decides to up and die instead of going down > cleanly... I guess the answer is that libvirt is just an abstraction layer above various hypervisors. We leave these higher level operations to management tools, of which there are several (eg. oVirt - see my previous email). Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From rjones at redhat.com Thu Jul 23 11:43:45 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Thu, 23 Jul 2009 12:43:45 +0100 Subject: [fedora-virt] ANNOUNCE: libguestfs 1.0.64 released Message-ID: <20090723114345.GA28829@amd.home.annexia.org> I'm pleased to announce the release of libguestfs 1.0.64, the library for accessing and modifying virtual machine disk images. Homepage: http://libguestfs.org/ Downloads: http://libguestfs.org/download/ Git repo: http://git.et.redhat.com/?p=libguestfs.git Fedora builds: http://koji.fedoraproject.org/koji/packageinfo?packageID=8391 NOTE at present there is a bug in qemu's vmchannel which stops libguestfs from working correctly with the very latest qemu from git. Use a stable 0.10.X version, or apply this patch: http://lists.gnu.org/archive/html/qemu-devel/2009-07/msg01753.html (These release notes include changes since the previous announcement, which was for 1.0.59) * New tool: virt-cat. This tool lets you copy out files from a guest. See this page for some interesting and unexpected uses: http://libguestfs.org/virt-cat.1.html#examples * Added libguestfs-test-tool which is a tool you can use to diagnose qemu / kernel booting problems, and also make bug reports more useful. * [Sys::Guestfs::Lib] split $os->{version} into $os->{major_version} and $os->{minor_version}. Add feature tags. (Matt Booth). * Allow TMPDIR to be used to override the location of temporary files. * Implement the guestfs_read_file call. * New calls guestfs_mkmountpoint and guestfs_rmmountpoint to allow some specialized read-only or nested filesystems to be mounted, particularly for examining live CDs. http://rwmj.wordpress.com/2009/07/15/unpack-the-russian-doll-of-a-f11-live-cd/ * New call guestfs_mountpoints to return a hash of device -> mountpoint. * Many documentation fixes, including an "API Overview" section which will help developers navigate parts of the now very large libguestfs API. http://libguestfs.org/guestfs.3.html#api_overview * Add ~ and ~username expansion in guestfish (RHBZ#511372). * Add kernel modules for reading DOS filesystems (Guido Gunther). * Add i18n support for Perl strings. Bugs fixed: * Fix guestfish -i / virt-inspector when working with libvirt domain names, so now 'guestfish -i libvirtdom' really works. * Detect renamed guestfwd support for vmchannel in upstream qemu. * Always pass noapic on kernel command line (workaround for RHBZ#502058) * Workaround for udev timeouts. * Check /usr/libexec for qemu binary, for RHEL 5.4. * Multiple fixes for non-srcdir builds. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://et.redhat.com/~rjones/virt-top From rich at lat.com Thu Jul 23 19:01:40 2009 From: rich at lat.com (Rich Mahn) Date: Thu, 23 Jul 2009 15:01:40 -0400 Subject: [fedora-virt] networking in virtual machines using libvirt tools Message-ID: <200907231901.n6NJ1eI0024650@raspberry.lat.com> I am trying to set up a virtual machine that has a routable IP address on the same subnet (and physically the same ethernet card) as the host machine, running f11 on the host. Using virsh and related, I can easily set up the network on the VM as a natted IP with dhcp. This is taken care of in the defaults for virt-manager. I can also set up, (but not quite as easily) the network the way I want on a CentOS/XEN host. Unfortunately CentOS doesn't have a number of other features that I want/need. So...is there some XML snippet I can add to the domain that will do what I want automatically? Or is there a script (or maybe I need to write one) that can be invoked to set up the interfaces? I would certainly be appreciative to get some pointers on how to proceed. To make what I want a little clearer: My host has a routable IP address such as 123.45.67.89. I want my VM to have the routable IP address 123.45.67.90. I realize I could probably do this with iptables on the host and using the 192.168.x.x IP on the VM, but then the VM has an incorrect idea of it's correct IP. Any help is appreciated. Thanks. From markmc at redhat.com Fri Jul 24 07:58:00 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 24 Jul 2009 08:58:00 +0100 Subject: [fedora-virt] networking in virtual machines using libvirt tools In-Reply-To: <200907231901.n6NJ1eI0024650@raspberry.lat.com> References: <200907231901.n6NJ1eI0024650@raspberry.lat.com> Message-ID: <1248422280.3046.11.camel@blaa> On Thu, 2009-07-23 at 15:01 -0400, Rich Mahn wrote: > I am trying to set up a virtual machine that has a routable IP address > on the same subnet (and physically the same ethernet card) as the host > machine, running f11 on the host. > > Using virsh and related, I can easily set up the network on the VM as > a natted IP with dhcp. This is taken care of in the defaults for > virt-manager. I can also set up, (but not quite as easily) the > network the way I want on a CentOS/XEN host. Unfortunately CentOS > doesn't have a number of other features that I want/need. > > So...is there some XML snippet I can add to the domain that will > do what I want automatically? Or is there a script (or maybe I need > to write one) that can be invoked to set up the interfaces? > > I would certainly be appreciative to get some pointers on how to proceed. > > To make what I want a little clearer: > > My host has a routable IP address such as 123.45.67.89. I want my > VM to have the routable IP address 123.45.67.90. Have you seen this? http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging Unless I misunderstand, all you need to do is create a bridge for the interface in the host, connect the guest's network backend in the host and statically configure the guest's interface with that IP address. Cheers, Mark. From rich at lat.com Fri Jul 24 12:07:01 2009 From: rich at lat.com (Rich Mahn) Date: Fri, 24 Jul 2009 08:07:01 -0400 Subject: [fedora-virt] networking in virtual machines using libvirt tools In-Reply-To: Your message of "Fri, 24 Jul 2009 08:58:00 BST." <1248422280.3046.11.camel@blaa> Message-ID: <200907241207.n6OC71js022592@raspberry.lat.com> > On Thu, 2009-07-23 at 15:01 -0400, Rich Mahn wrote: > > I am trying to set up a virtual machine that has a routable IP address > > on the same subnet (and physically the same ethernet card) as the host > > machine, running f11 on the host. > > > > Using virsh and related, I can easily set up the network on the VM as > > a natted IP with dhcp. This is taken care of in the defaults for > > virt-manager. I can also set up, (but not quite as easily) the > > network the way I want on a CentOS/XEN host. Unfortunately CentOS > > doesn't have a number of other features that I want/need. > > > > So...is there some XML snippet I can add to the domain that will > > do what I want automatically? Or is there a script (or maybe I need > > to write one) that can be invoked to set up the interfaces? > > > > I would certainly be appreciative to get some pointers on how to proceed. > > > > To make what I want a little clearer: > > > > My host has a routable IP address such as 123.45.67.89. I want my > > VM to have the routable IP address 123.45.67.90. > Have you seen this? > http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging > Unless I misunderstand, all you need to do is create a bridge for the > interface in the host, connect the guest's network backend in the host > and statically configure the guest's interface with that IP address. > Cheers, > Mark. Thanks Mark. That is exactly what I was looking for. I'll try it out and report back. Rich From l.cranston at gmail.com Fri Jul 24 15:13:26 2009 From: l.cranston at gmail.com (lamont cranston) Date: Fri, 24 Jul 2009 11:13:26 -0400 Subject: [fedora-virt] virt-what 1.1 released In-Reply-To: <20090723090653.GA32278@amd.home.annexia.org> References: <20090723090653.GA32278@amd.home.annexia.org> Message-ID: <4502be8f0907240813m4515c66an90fba22f40f4ec50@mail.gmail.com> Just curious, does it detect Hyper-V also? On Thu, Jul 23, 2009 at 5:06 AM, Richard W.M. Jones wrote: > > I just released virt-what 1.1. This program is a collection of code > snippets to allow you to determine what sort of virtualization you are > running inside. > > The new version can tell the difference between QEMU and KVM, and can > tell if you are running inside a Xen fullvirt guest. > > Home page: http://et.redhat.com/~rjones/virt-what/ > Downloads: http://et.redhat.com/~rjones/virt-what/files/ > Repository: http://git.et.redhat.com/?p=virt-what.git;a=summary > > Rich. > > -- > Richard Jones, Emerging Technologies, Red Hat > http://et.redhat.com/~rjones > New in Fedora 11: Fedora Windows cross-compiler. Compile Windows > programs, test, and build Windows installers. Over 70 libraries supprt'd > http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt > -- (\__/) (='.'=) (")_(") -------------- next part -------------- An HTML attachment was scrubbed... URL: From rjones at redhat.com Fri Jul 24 15:34:08 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Fri, 24 Jul 2009 16:34:08 +0100 Subject: [fedora-virt] virt-what 1.1 released In-Reply-To: <4502be8f0907240813m4515c66an90fba22f40f4ec50@mail.gmail.com> References: <20090723090653.GA32278@amd.home.annexia.org> <4502be8f0907240813m4515c66an90fba22f40f4ec50@mail.gmail.com> Message-ID: <20090724153408.GA14638@amd.home.annexia.org> On Fri, Jul 24, 2009 at 11:13:26AM -0400, lamont cranston wrote: > Just curious, does it detect Hyper-V also? Possibly. There is support for VirtualPC, which AIUI is the predecessor to Hyper-V (the company that Microsoft bought to get the technology). I have no access to VirtualPC or Hyper-V to test this, but if you have access, please let me know if it works. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rich at lat.com Fri Jul 24 16:18:30 2009 From: rich at lat.com (Rich Mahn) Date: Fri, 24 Jul 2009 12:18:30 -0400 Subject: [fedora-virt] networking in virtual machines using libvirt tools In-Reply-To: Your message of "Fri, 24 Jul 2009 08:07:01 EDT." <200907241207.n6OC71js022592@raspberry.lat.com> Message-ID: <200907241618.n6OGIUE1004826@raspberry.lat.com> === snip snip === > > Have you seen this? > > http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging > > Unless I misunderstand, all you need to do is create a bridge for the > > interface in the host, connect the guest's network backend in the host > > and statically configure the guest's interface with that IP address. > > Cheers, > > Mark. > Thanks Mark. That is exactly what I was looking for. I'll try it out > and report back. > Rich The instructions are for F9 and as such have a couple very minor problems. For example, I can't find lokkit for f11. However, other than that, I just pretty much followed the cookbook to get things working. I had a small problem with the networking until I noticed that the cookbook was configured for dhcp and I use fixed IPs. Once I corrected for that everything worked GREAT!!!! I looked around the site and that wiki.libvirt.org has some really great information available. Thanks loads. rich From rich at lat.com Fri Jul 24 16:39:54 2009 From: rich at lat.com (Rich Mahn) Date: Fri, 24 Jul 2009 12:39:54 -0400 Subject: [fedora-virt] swap space on virtual machines Message-ID: <200907241639.n6OGdsTN006424@raspberry.lat.com> How big should the swap parititons be on virtual machines under qemu, qemu/kvm? It seems to me that if the VM actually needs swap space, it would be more efficient to allocate more virual memory to it. I know it's possible to allocate more virtual memory than there is physical memory. Intuitively (which isn't always right) it would seem that allocating more memory is more efficient than letting the VM use swap space. It would seem that the host machine would have to either use physical memory or swap space if it's required. Compared to the VM using a swap space that is a virtual disk space that goes to real disk. Thoughts anyone?? rich From eb30750 at gmail.com Sat Jul 25 07:17:38 2009 From: eb30750 at gmail.com (Paul Lambert) Date: Sat, 25 Jul 2009 02:17:38 -0500 Subject: [fedora-virt] febootstrap purpose status Message-ID: <4A6AB192.2000107@gmail.com> Can I get an explanation of the targeted users of this distro? The reason I ask is twofold. 1) I am looking for a bare metal OS to base real time control on and 2) I believe that VMware has it right with respects to hypervisor architecture. Again, a bare metal host with the actual guest OS running the interface and application code. My current configuration using Fedora 11 as the host and running WinXP as a guest is what I term the "workstation" mode. The host OS still performs user interface and file storage functions for users. This is the same as using VMware workstation. The full hyperviser mode would be a minimum Fedora build that allows a command line only interface. No graphics libraries or other user intereface systems. This is essentially ESX. I would create a Fedora 11 appliance and a WinXP appliance and import these through command line instructions. (Or better yet, Fedora would release a distro that included installing the bare metal version and the full Fedora appliance.) The Fedora guest then could connect back to the bare metal host to perform monitoring and VM management function (oVirt). I want this on my laptop. Upgrading the host while it is also serving as a workstation is too risky and a lot of work to perform OS testing and evaluation. It's too easy to copy out one's guest VMs and reload or upgrade the host. Then when this activity is complete just reinstall the original host and VM appliances. Backup and restore are much easier as well. The last I saw on the febootstrap size I believe it was just under 20 mb. This still seams extremely large for a bare metal system. I need the Fedora filesystem with KVM and the hardware driver library. How small can we go? I would like to try this. Thanks for any feedback and direction Paul From agx at sigxcpu.org Sat Jul 25 01:17:26 2009 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Sat, 25 Jul 2009 03:17:26 +0200 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> Message-ID: <20090725011726.GA3615@bogon.sigxcpu.org> On Mon, Jul 20, 2009 at 10:45:56AM +0200, Gianluca Cecchi wrote: > Hello, > is there any pointer about how to set up a cluster of Qemu/KVM hosts? > I'm on F11 x86_64 for the hosts. > I read requirements for KVM migration in general highlighted at > http://www.linux-kvm.org/page/Migration but I keep having doubts, in > particular regarding libvirt configuration in cluster environments... > Some questions about libvirt configuration: > - /etc/libvirt/qemu/networks > do the files inside here be identical between hosts (default.xml and > other custom configured network ones)? > What are the uuid tags into the xml for? Do they have to be identical > for clusters or do they have to be absolutely different for a sort of > "identification" of host (as the term seems to suggest)? > If I have guests that use virbr0 and use dhcp for their network > config, and want two different qemu/kvm hosts able to migrate these > guests between them, need to have same config or what? > - the same for storage configuration and other parameters. You can use rhcs or pacemaker for this and share the vm configuration via e.g. gfs. Cheers, -- Guido From gianluca.cecchi at gmail.com Sat Jul 25 10:11:40 2009 From: gianluca.cecchi at gmail.com (Gianluca Cecchi) Date: Sat, 25 Jul 2009 12:11:40 +0200 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <20090725011726.GA3615@bogon.sigxcpu.org> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> <20090725011726.GA3615@bogon.sigxcpu.org> Message-ID: <561c252c0907250311v124f1b64m26ffb7d233aefa76@mail.gmail.com> I' using rhcs, but I'm trying to setup a sort of actve active config. Where I have also clvmd and where I can have for example some LVs of a clustered VG active as disks of some VMs hosted on one server, while other LVs of this VG represent disks hosted on another host. Also, as I have no SAN in my test env I'm using drbd 8.3.2 in dual primary mode... Before starting with the cluster arch I had been done tests with Qemu/Kvm and virt-manager using a standalone host. Then without restarting from zero and deleting things, I transformed my local VG into a drbd based one and I cloned the initial host So the question arised about uuid values inside xml files... and for example if they have to be the same for storage config and network config or not... I would like not to use GFS, so that I don't add another layer impacting performance and complexity.... But your saying I can use GFS for config does implicitly mean same config files, also in active-active config? Gianluca On Sat, Jul 25, 2009 at 3:17 AM, Guido G?nther wrote: > On Mon, Jul 20, 2009 at 10:45:56AM +0200, Gianluca Cecchi wrote: >> Hello, >> is there any pointer about how to set up a cluster of Qemu/KVM hosts? >> I'm on F11 x86_64 for the hosts. >> I read requirements for KVM migration in general highlighted at >> http://www.linux-kvm.org/page/Migration but I keep having doubts, in >> particular regarding libvirt configuration in cluster environments... >> Some questions about libvirt configuration: >> - /etc/libvirt/qemu/networks >> do the files inside here be identical between hosts (default.xml and >> other custom configured network ones)? >> What are the uuid tags into the xml for? Do they have to be identical >> for clusters or do they have to be absolutely different for a sort of >> "identification" of host (as the term seems to suggest)? >> If I have guests that use virbr0 and use dhcp for their network >> config, and want two different qemu/kvm hosts able to migrate these >> guests between them, ?need to have same config or what? >> - the same for storage configuration and other parameters. > You can use rhcs or pacemaker for this and share the vm configuration > via e.g. gfs. > Cheers, > ?-- Guido > From agx at sigxcpu.org Sat Jul 25 13:31:06 2009 From: agx at sigxcpu.org (Guido =?iso-8859-1?Q?G=FCnther?=) Date: Sat, 25 Jul 2009 15:31:06 +0200 Subject: [fedora-virt] libvirt configuration for cluster of qemu/kvm hosts In-Reply-To: <561c252c0907250311v124f1b64m26ffb7d233aefa76@mail.gmail.com> References: <561c252c0907200145o18d35bd3n227ce1a48aaab956@mail.gmail.com> <20090725011726.GA3615@bogon.sigxcpu.org> <561c252c0907250311v124f1b64m26ffb7d233aefa76@mail.gmail.com> Message-ID: <20090725133106.GB21432@bogon.sigxcpu.org> On Sat, Jul 25, 2009 at 12:11:40PM +0200, Gianluca Cecchi wrote: [..snip..] > So the question arised about uuid values inside xml files... and for > example if they have to be the same for storage config and network > config or not... In principle they don't have to be the same across hosts since you can identify the network by name and the volumes by their path but I prefer to keep them in sync (using shared nfs in my case). > I would like not to use GFS, so that I don't add another layer > impacting performance and complexity.... Keeping the storge in LVM without filesystem should be fine. > But your saying I can use GFS for config does implicitly mean same > config files, also in active-active config? Yes sure. I share configs across hosts and reload libvirtd's configuration when adding new kvm vms so it picks up the new configuration. Hope that helps, -- Guido From rjones at redhat.com Sat Jul 25 18:02:58 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sat, 25 Jul 2009 19:02:58 +0100 Subject: [fedora-virt] swap space on virtual machines In-Reply-To: <200907241639.n6OGdsTN006424@raspberry.lat.com> References: <200907241639.n6OGdsTN006424@raspberry.lat.com> Message-ID: <20090725180258.GA20762@amd.home.annexia.org> On Fri, Jul 24, 2009 at 12:39:54PM -0400, Rich Mahn wrote: > How big should the swap parititons be on virtual machines > under qemu, qemu/kvm? > > It seems to me that if the VM actually needs swap space, it > would be more efficient to allocate more virual memory to it. > I know it's possible to allocate more virtual > memory than there is physical memory. Intuitively (which > isn't always right) it would seem that allocating more > memory is more efficient than letting the VM use swap space. > It would seem that the host machine would have to either use > physical memory or swap space if it's required. A real interesting question. One place I think you're wrong is the assumption that adding more memory to a VM is better than having the VM use a swap disk. The reason would be that the VM's memory manager will assume that the [from its point of view] physical memory will be much faster than swap, and so will arrange memory vs swap use accordingly. But this assumption isn't true, this so-called physical memory is really just as slow as swap! You say: > Compared to the VM using a swap space that is a virtual disk space > that goes to real disk. but actually virtualized block I/O isn't so bad if you use the correct (virtio) drivers. I think the only way you'll really answer this is to conduct tests based on your specific workload. I've only done this with Xen, where this doesn't apply because Xen guest memory _is_ physical memory. By the way, Kernel Shared Memory (KSM, [1]) complicates everything... Rich. [1] http://lwn.net/Articles/306704/ -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From rjones at redhat.com Sat Jul 25 18:12:08 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Sat, 25 Jul 2009 19:12:08 +0100 Subject: [fedora-virt] febootstrap purpose status In-Reply-To: <4A6AB192.2000107@gmail.com> References: <4A6AB192.2000107@gmail.com> Message-ID: <20090725181208.GB20762@amd.home.annexia.org> On Sat, Jul 25, 2009 at 02:17:38AM -0500, Paul Lambert wrote: > Can I get an explanation of the targeted users of this distro? There's a bit of confusion in your post, so to get some facts out the way first: (a) febootstrap is a shell script that runs yum as non-root, and comes with some other shell scripts which can trim the fat from Fedora, but they are not essential to its purpose which is just to run yum without needing root privileges. (b) It's only designed for people who want to run yum as non-root. Specifically this is a requirement for building and running libguestfs. (c) febootstrap installs standard yum-based distributions, ie. Fedora, Red Hat Enterprise Linux, CentOS and probably others. > The > reason I ask is twofold. 1) I am looking for a bare metal OS to base > real time control on and 2) I believe that VMware has it right with > respects to hypervisor architecture. Again, a bare metal host with the > actual guest OS running the interface and application code. > > My current configuration using Fedora 11 as the host and running WinXP > as a guest is what I term the "workstation" mode. The host OS still > performs user interface and file storage functions for users. This is > the same as using VMware workstation. The full hyperviser mode would be > a minimum Fedora build that allows a command line only interface. No > graphics libraries or other user intereface systems. This is > essentially ESX. I would create a Fedora 11 appliance and a WinXP > appliance and import these through command line instructions. (Or > better yet, Fedora would release a distro that included installing the > bare metal version and the full Fedora appliance.) The Fedora guest > then could connect back to the bare metal host to perform monitoring and > VM management function (oVirt). Honestly I think what you're looking for _is_ the hypervisor component of oVirt. This component at the moment isn't built with febootstrap (it uses some kickstart stuff that has to run as root), but it's on their roadmap to use febootstrap or something like it, post-F12. > I want this on my laptop. Upgrading the host while it is also serving > as a workstation is too risky and a lot of work to perform OS testing > and evaluation. It's too easy to copy out one's guest VMs and reload or > upgrade the host. Then when this activity is complete just reinstall > the original host and VM appliances. Backup and restore are much easier > as well. > > The last I saw on the febootstrap size I believe it was just under 20 > mb. This still seams extremely large for a bare metal system. I need > the Fedora filesystem with KVM and the hardware driver library. How > small can we go? I would like to try this. Honestly, if you want libvirt, KVM etc. you won't get much smaller than 100 MB (filesystem) + ~ 200 MB (RAM required by the host). Fedora just isn't very well suited to building minimal versions like that. If the above numbers are too big, then you should look at a specific minimal Linux distro. For why we didn't use that in libguestfs, see: http://rwmj.wordpress.com/2009/03/20/why-not-use-a-minimal-distribution/ Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From dlaor at redhat.com Sun Jul 26 09:58:32 2009 From: dlaor at redhat.com (Dor Laor) Date: Sun, 26 Jul 2009 12:58:32 +0300 Subject: [fedora-virt] swap space on virtual machines In-Reply-To: <20090725180258.GA20762@amd.home.annexia.org> References: <200907241639.n6OGdsTN006424@raspberry.lat.com> <20090725180258.GA20762@amd.home.annexia.org> Message-ID: <4A6C28C8.5010400@redhat.com> On 07/25/2009 09:02 PM, Richard W.M. Jones wrote: > On Fri, Jul 24, 2009 at 12:39:54PM -0400, Rich Mahn wrote: >> How big should the swap parititons be on virtual machines >> under qemu, qemu/kvm? >> >> It seems to me that if the VM actually needs swap space, it >> would be more efficient to allocate more virual memory to it. >> I know it's possible to allocate more virtual >> memory than there is physical memory. Intuitively (which >> isn't always right) it would seem that allocating more >> memory is more efficient than letting the VM use swap space. >> It would seem that the host machine would have to either use >> physical memory or swap space if it's required. > > A real interesting question. > > One place I think you're wrong is the assumption that adding more > memory to a VM is better than having the VM use a swap disk. The > reason would be that the VM's memory manager will assume that the > [from its point of view] physical memory will be much faster than > swap, and so will arrange memory vs swap use accordingly. But this > assumption isn't true, this so-called physical memory is really just > as slow as swap! > > You say: > >> Compared to the VM using a swap space that is a virtual disk space >> that goes to real disk. > > but actually virtualized block I/O isn't so bad if you use the correct > (virtio) drivers. > I think several terms are mixed together here: The guest is given certain amount of ram to play with. Various hypervisors virtualize this guest ram differently. Regardless of the hypervisor. The guest does assumes it is his ram. Even if you allocate large amount of ram to the guest, it might swap since the guest runs processes that uses virtual memory, and thus might exceed the allocated ram to the guest. Guest swapping is a reasonable scenario that should be allowed and supported. When using a fast virtual block device like virtio, it should even be almost as fast as native swapping (which is always slower then ram..). KVM hypervisor runs a VM as standard process. As such, it allocate virtual userspace memory to the VM as ram. We can overcommit the host ram and even swap it from the host. Host swapping works nicely but might really slow down things since both host & guest will swap out/in/out the same pages. > I think the only way you'll really answer this is to conduct tests > based on your specific workload. I've only done this with Xen, where > this doesn't apply because Xen guest memory _is_ physical memory. > > By the way, Kernel Shared Memory (KSM, [1]) complicates everything... But make things better ;) > > Rich. > > [1] http://lwn.net/Articles/306704/ > So bottom line, if you have free ram, give it to the guest - why save it? Even large guest can swap, determined by the load. Dor From rich at lat.com Sun Jul 26 12:48:23 2009 From: rich at lat.com (Rich Mahn) Date: Sun, 26 Jul 2009 08:48:23 -0400 Subject: [fedora-virt] swap space on virtual machines In-Reply-To: <4A6C28C8.5010400@redhat.com> References: <200907241639.n6OGdsTN006424@raspberry.lat.com> <20090725180258.GA20762@amd.home.annexia.org> <4A6C28C8.5010400@redhat.com> Message-ID: <4A6C5097.7090903@lat.com> Dor Laor wrote: > On 07/25/2009 09:02 PM, Richard W.M. Jones wrote: >> On Fri, Jul 24, 2009 at 12:39:54PM -0400, Rich Mahn wrote: >>> How big should the swap parititons be on virtual machines >>> under qemu, qemu/kvm? >>> >>> It seems to me that if the VM actually needs swap space, it >>> would be more efficient to allocate more virual memory to it. >>> I know it's possible to allocate more virtual >>> memory than there is physical memory. Intuitively (which >>> isn't always right) it would seem that allocating more >>> memory is more efficient than letting the VM use swap space. >>> It would seem that the host machine would have to either use >>> physical memory or swap space if it's required. >> >> A real interesting question. >> >> One place I think you're wrong is the assumption that adding more >> memory to a VM is better than having the VM use a swap disk. The >> reason would be that the VM's memory manager will assume that the >> [from its point of view] physical memory will be much faster than >> swap, and so will arrange memory vs swap use accordingly. But this >> assumption isn't true, this so-called physical memory is really just >> as slow as swap! >> >> You say: >> >>> Compared to the VM using a swap space that is a virtual disk space >>> that goes to real disk. >> >> but actually virtualized block I/O isn't so bad if you use the correct >> (virtio) drivers. >> > > I think several terms are mixed together here: > > The guest is given certain amount of ram to play with. > Various hypervisors virtualize this guest ram differently. Regardless of > the hypervisor. The guest does assumes it is his ram. > Even if you allocate large amount of ram to the guest, it might swap > since the guest runs processes that uses virtual memory, and thus might > exceed the allocated ram to the guest. Guest swapping is a reasonable > scenario that should be allowed and supported. > When using a fast virtual block device like virtio, it should even be > almost as fast as native swapping (which is always slower then ram..). > > KVM hypervisor runs a VM as standard process. As such, it allocate > virtual userspace memory to the VM as ram. We can overcommit the host > ram and even swap it from the host. > Host swapping works nicely but might really slow down things since both > host & guest will swap out/in/out the same pages. > > >> I think the only way you'll really answer this is to conduct tests >> based on your specific workload. I've only done this with Xen, where >> this doesn't apply because Xen guest memory _is_ physical memory. >> >> By the way, Kernel Shared Memory (KSM, [1]) complicates everything... > > But make things better ;) > >> >> Rich. >> >> [1] http://lwn.net/Articles/306704/ >> > > So bottom line, if you have free ram, give it to the guest - why save > it? Even large guest can swap, determined by the load. > > Dor Okay, my understanding of how RAM is used in Linux is limited. If a system has, say 1G of RAM and runs fine without swapping, doesn't that same system usually run better with 2G of RAM? In other words, doesn't the OS sprawl out to use all available RAM, with disk cache, or some such other items? If that's the case, then it's important not to allocate more RAM to VMs than is actually available. OTOH, if the OS doesn't sprawl out and only uses the same amount of memory (assuming no swapping is needed) regardless of the amount of physical memory, then oversubscribing the RAM allocated to VMs shouldn't be a problem if most of the time they don't use it. While I'm asking questions, I know that I can use 'swapon -s' to get the current swap situation. Is there a command I can use to get more information on swap usage, such as high watermark, average usage, or some such data? Thanks, Rich -------------- next part -------------- No virus found in this outgoing message. Checked by AVG - www.avg.com Version: 8.5.392 / Virus Database: 270.13.30/2263 - Release Date: 07/26/09 06:33:00 From dlaor at redhat.com Sun Jul 26 14:22:48 2009 From: dlaor at redhat.com (Dor Laor) Date: Sun, 26 Jul 2009 17:22:48 +0300 Subject: [fedora-virt] swap space on virtual machines In-Reply-To: <4A6C5097.7090903@lat.com> References: <200907241639.n6OGdsTN006424@raspberry.lat.com> <20090725180258.GA20762@amd.home.annexia.org> <4A6C28C8.5010400@redhat.com> <4A6C5097.7090903@lat.com> Message-ID: <4A6C66B8.7030204@redhat.com> On 07/26/2009 03:48 PM, Rich Mahn wrote: > Dor Laor wrote: >> On 07/25/2009 09:02 PM, Richard W.M. Jones wrote: >>> On Fri, Jul 24, 2009 at 12:39:54PM -0400, Rich Mahn wrote: >>>> How big should the swap parititons be on virtual machines >>>> under qemu, qemu/kvm? >>>> >>>> It seems to me that if the VM actually needs swap space, it >>>> would be more efficient to allocate more virual memory to it. >>>> I know it's possible to allocate more virtual >>>> memory than there is physical memory. Intuitively (which >>>> isn't always right) it would seem that allocating more >>>> memory is more efficient than letting the VM use swap space. >>>> It would seem that the host machine would have to either use >>>> physical memory or swap space if it's required. >>> A real interesting question. >>> >>> One place I think you're wrong is the assumption that adding more >>> memory to a VM is better than having the VM use a swap disk. The >>> reason would be that the VM's memory manager will assume that the >>> [from its point of view] physical memory will be much faster than >>> swap, and so will arrange memory vs swap use accordingly. But this >>> assumption isn't true, this so-called physical memory is really just >>> as slow as swap! >>> >>> You say: >>> >>>> Compared to the VM using a swap space that is a virtual disk space >>>> that goes to real disk. >>> but actually virtualized block I/O isn't so bad if you use the correct >>> (virtio) drivers. >>> >> I think several terms are mixed together here: >> >> The guest is given certain amount of ram to play with. >> Various hypervisors virtualize this guest ram differently. Regardless of >> the hypervisor. The guest does assumes it is his ram. >> Even if you allocate large amount of ram to the guest, it might swap >> since the guest runs processes that uses virtual memory, and thus might >> exceed the allocated ram to the guest. Guest swapping is a reasonable >> scenario that should be allowed and supported. >> When using a fast virtual block device like virtio, it should even be >> almost as fast as native swapping (which is always slower then ram..). >> >> KVM hypervisor runs a VM as standard process. As such, it allocate >> virtual userspace memory to the VM as ram. We can overcommit the host >> ram and even swap it from the host. >> Host swapping works nicely but might really slow down things since both >> host& guest will swap out/in/out the same pages. >> >> >>> I think the only way you'll really answer this is to conduct tests >>> based on your specific workload. I've only done this with Xen, where >>> this doesn't apply because Xen guest memory _is_ physical memory. >>> >>> By the way, Kernel Shared Memory (KSM, [1]) complicates everything... >> But make things better ;) >> >>> Rich. >>> >>> [1] http://lwn.net/Articles/306704/ >>> >> So bottom line, if you have free ram, give it to the guest - why save >> it? Even large guest can swap, determined by the load. >> >> Dor > > Okay, my understanding of how RAM is used in Linux is limited. If a > system has, say 1G of RAM and runs fine without swapping, doesn't that > same system usually run better with 2G of RAM? In other words, doesn't > the OS sprawl out to use all available RAM, with disk cache, or some It depends on the load. If the VM is idle, then it won't have any effect. If the VM does not need allot of memory, the same. If the VM swaps, sure it will help. > such other items? If that's the case, then it's important not to > allocate more RAM to VMs than is actually available. OTOH, if the OS Again, depending on the host load. You can overcommit VM memory and it might be good if you have many VMs that have low memory foot print. If it is not the case, you better not do it. > doesn't sprawl out and only uses the same amount of memory (assuming no > swapping is needed) regardless of the amount of physical memory, then > oversubscribing the RAM allocated to VMs shouldn't be a problem if most > of the time they don't use it. > > While I'm asking questions, I know that I can use 'swapon -s' to get the > current swap situation. Is there a command I can use to get more > information on swap usage, such as high watermark, average usage, or > some such data? You can use vmstat 1 to track the io activity. Even tweaking the sysctl is possible. > > Thanks, > Rich > > > > ------------------------------------------------------------------------ > > > No virus found in this outgoing message. > Checked by AVG - www.avg.com > Version: 8.5.392 / Virus Database: 270.13.30/2263 - Release Date: 07/26/09 06:33:00 > > > > ------------------------------------------------------------------------ > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt From dennisml at conversis.de Mon Jul 27 13:15:05 2009 From: dennisml at conversis.de (Dennis J.) Date: Mon, 27 Jul 2009 15:15:05 +0200 Subject: [fedora-virt] I/O load distribution Message-ID: <4A6DA859.3060000@conversis.de> Hi, What is the best way to deal with I/O load when running several VMs on a physical machine with local or remote storage? What I'm primarily worried about is the case when several VMs cause disk I/O at the same time. One example would be the "updatedb" cronjob of the mlocate package. If you have say 5 VMs running on a physical System with a local software raid-1 as storage and the all run updatedb at the same time that causes all of them to run really slowly because the starve each other fighting over the disk. What is the best way to soften the impact of such a situation? Does it make sense to use a hardware raid instead? How would the raid type affect the performance in this case? Would the fact that the I/O load gets distributed across multiple spindles in, say, a 4 disk hardware raid-5 have a big impact on this? I'm currently facing the problem where I fear that random disk I/O by too many VMs on a physical system could cripple their performance even though I have plenty of CPU cores/RAM left to run them. Has anyone experience with this problem and maybe some data to shed some light on this potential bottleneck for virtualization? Regards, Dennis From pasik at iki.fi Mon Jul 27 16:22:27 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Mon, 27 Jul 2009 19:22:27 +0300 Subject: [fedora-virt] I/O load distribution In-Reply-To: <4A6DA859.3060000@conversis.de> References: <4A6DA859.3060000@conversis.de> Message-ID: <20090727162227.GV24960@edu.joroinen.fi> On Mon, Jul 27, 2009 at 03:15:05PM +0200, Dennis J. wrote: > Hi, > What is the best way to deal with I/O load when running several VMs on a > physical machine with local or remote storage? > > What I'm primarily worried about is the case when several VMs cause disk > I/O at the same time. One example would be the "updatedb" cronjob of the > mlocate package. If you have say 5 VMs running on a physical System with a > local software raid-1 as storage and the all run updatedb at the same time > that causes all of them to run really slowly because the starve each other > fighting over the disk. > > What is the best way to soften the impact of such a situation? Does it make > sense to use a hardware raid instead? How would the raid type affect the > performance in this case? Would the fact that the I/O load gets distributed > across multiple spindles in, say, a 4 disk hardware raid-5 have a big > impact on this? > > I'm currently facing the problem where I fear that random disk I/O by too > many VMs on a physical system could cripple their performance even though I > have plenty of CPU cores/RAM left to run them. > > Has anyone experience with this problem and maybe some data to shed some > light on this potential bottleneck for virtualization? > Well, there's only so much IOPS you can get from a single disk.. (or raid1). IO generated from multiple virtual machines is pretty random, so you just need a lot of disks to make it faster. Single 7200 rpm SATA disk will give you only 100-150 IOPS (IOs per second) max.. 10 disks will give you 1000-1500 IOPS max.. it's pretty easy maths. Also good RAID controller with big battery-backed write-cache will help, in some cases a lot. If the IOS are not split evenly between VMs, you could use some tool like dm-ioband to make sure IOs are split fairly between VMs. -- Pasi From pasik at iki.fi Mon Jul 27 16:26:12 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Mon, 27 Jul 2009 19:26:12 +0300 Subject: [fedora-virt] Re: [Fedora-xen] Dom0 kernels / i686 kernel crash on boot In-Reply-To: <2cc75dd80907121859q227e715w2278f37568d73d41@mail.gmail.com> References: <2cc75dd80907121859q227e715w2278f37568d73d41@mail.gmail.com> Message-ID: <20090727162612.GW24960@edu.joroinen.fi> On Sun, Jul 12, 2009 at 09:59:09PM -0400, Lester M. wrote: > On Fri, Jul 10, 2009 at 7:11 PM, M A Young wrote: > > > Here is another update (kernel-2.6.31-0.1.2.40.rc2.git4.xendom0.fc12) at > > http://koji.fedoraproject.org/koji/taskinfo?taskID=1466158 and the > > repository http://fedorapeople.org/~myoung/dom0/. This updates to the latest rawhide source, I don't think there are > > significant changes on the xen side, so i686 may still be broken, though the > > x86_64 version works okay for me. > > > > Michael Young > > > > _______________________________________________ > > Fedora-virt mailing list > > Fedora-virt at redhat.com > > https://www.redhat.com/mailman/listinfo/fedora-virt > > > > > Hello Michael, > > I can confirm my same issue is still present. I used your latest updated > kernels (i686), still get a "Blank Screen", unresponsive system, that > require a hard reset. Was not able to get output after xen says "Scrubbing > free memory.......Done." > > I'll keep testing for ya, as you release them. :-) It's a known problem.. I've reported the issue to Jeremy, and also sent him the traceback and other info about the problem, but he hasn't had time yet to solve it. -- Pasi From pasik at iki.fi Mon Jul 27 16:27:23 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Mon, 27 Jul 2009 19:27:23 +0300 Subject: [fedora-virt] I/O load distribution In-Reply-To: <20090727162227.GV24960@edu.joroinen.fi> References: <4A6DA859.3060000@conversis.de> <20090727162227.GV24960@edu.joroinen.fi> Message-ID: <20090727162723.GX24960@edu.joroinen.fi> On Mon, Jul 27, 2009 at 07:22:27PM +0300, Pasi K?rkk?inen wrote: > On Mon, Jul 27, 2009 at 03:15:05PM +0200, Dennis J. wrote: > > Hi, > > What is the best way to deal with I/O load when running several VMs on a > > physical machine with local or remote storage? > > > > What I'm primarily worried about is the case when several VMs cause disk > > I/O at the same time. One example would be the "updatedb" cronjob of the > > mlocate package. If you have say 5 VMs running on a physical System with a > > local software raid-1 as storage and the all run updatedb at the same time > > that causes all of them to run really slowly because the starve each other > > fighting over the disk. > > > > What is the best way to soften the impact of such a situation? Does it make > > sense to use a hardware raid instead? How would the raid type affect the > > performance in this case? Would the fact that the I/O load gets distributed > > across multiple spindles in, say, a 4 disk hardware raid-5 have a big > > impact on this? > > > > I'm currently facing the problem where I fear that random disk I/O by too > > many VMs on a physical system could cripple their performance even though I > > have plenty of CPU cores/RAM left to run them. > > > > Has anyone experience with this problem and maybe some data to shed some > > light on this potential bottleneck for virtualization? > > > > Well, there's only so much IOPS you can get from a single disk.. (or raid1). > > IO generated from multiple virtual machines is pretty random, so you just > need a lot of disks to make it faster. > > Single 7200 rpm SATA disk will give you only 100-150 IOPS (IOs per second) > max.. 10 disks will give you 1000-1500 IOPS max.. it's pretty easy maths. > .. Or then get faster disks. Single 15k rpm SAS disk will give you up to 350 IOPS, so it's 2-3x faster than 7200 rpm SATA. -- Pasi From rjones at redhat.com Mon Jul 27 16:44:06 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 27 Jul 2009 17:44:06 +0100 Subject: [fedora-virt] swap space on virtual machines In-Reply-To: <4A6C5097.7090903@lat.com> References: <200907241639.n6OGdsTN006424@raspberry.lat.com> <20090725180258.GA20762@amd.home.annexia.org> <4A6C28C8.5010400@redhat.com> <4A6C5097.7090903@lat.com> Message-ID: <20090727164406.GA9427@amd.home.annexia.org> On Sun, Jul 26, 2009 at 08:48:23AM -0400, Rich Mahn wrote: > Okay, my understanding of how RAM is used in Linux is limited. If a > system has, say 1G of RAM and runs fine without swapping, doesn't that > same system usually run better with 2G of RAM? In other words, doesn't > the OS sprawl out to use all available RAM, with disk cache, or some > such other items? If that's the case, then it's important not to > allocate more RAM to VMs than is actually available. Most guests access their own disk exclusively, so there is not a problem that two guests will try to cache the same bit of disk. This would argue in favour of increasing guest size, provided that guest physical RAM is as fast as host physical RAM (which it nearly is, provided you don't overcommit memory). > While I'm asking questions, I know that I can use 'swapon -s' to get the > current swap situation. Is there a command I can use to get more > information on swap usage, such as high watermark, average usage, or > some such data? Apart from free(1) which will give you the current overview, maybe try 'vmstat -s' or something like collectd. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://et.redhat.com/~rjones/libguestfs/ See what it can do: http://et.redhat.com/~rjones/libguestfs/recipes.html From rjones at redhat.com Mon Jul 27 16:47:08 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Mon, 27 Jul 2009 17:47:08 +0100 Subject: [fedora-virt] I/O load distribution In-Reply-To: <4A6DA859.3060000@conversis.de> References: <4A6DA859.3060000@conversis.de> Message-ID: <20090727164708.GB9427@amd.home.annexia.org> On Mon, Jul 27, 2009 at 03:15:05PM +0200, Dennis J. wrote: > What is the best way to deal with I/O load when running several VMs on a > physical machine with local or remote storage? > > What I'm primarily worried about is the case when several VMs cause disk > I/O at the same time. One example would be the "updatedb" cronjob of the > mlocate package. If you have say 5 VMs running on a physical System with > a local software raid-1 as storage and the all run updatedb at the same > time that causes all of them to run really slowly because the starve each > other fighting over the disk. > > What is the best way to soften the impact of such a situation? Does it > make sense to use a hardware raid instead? How would the raid type affect > the performance in this case? Would the fact that the I/O load gets > distributed across multiple spindles in, say, a 4 disk hardware raid-5 > have a big impact on this? > > I'm currently facing the problem where I fear that random disk I/O by too > many VMs on a physical system could cripple their performance even though > I have plenty of CPU cores/RAM left to run them. > > Has anyone experience with this problem and maybe some data to shed some > light on this potential bottleneck for virtualization? For KVM, each VM isn't really any different from a host process, so you have to deal with them the same way that you'd deal with having lots of host processes doing I/O. So: lots of spindles, expensive I/O hardware, etc. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones New in Fedora 11: Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 70 libraries supprt'd http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw From pasik at iki.fi Mon Jul 27 21:39:17 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Tue, 28 Jul 2009 00:39:17 +0300 Subject: [fedora-virt] Success with Fedora 10 Xen pv_ops 2.6.29-rc8 dom0 In-Reply-To: <20090324192846.GN19446@redhat.com> References: <20090324192502.GS5528@edu.joroinen.fi> <20090324192846.GN19446@redhat.com> Message-ID: <20090727213917.GZ24960@edu.joroinen.fi> On Tue, Mar 24, 2009 at 07:28:46PM +0000, Daniel P. Berrange wrote: > On Tue, Mar 24, 2009 at 09:25:02PM +0200, Pasi K?rkk?inen wrote: > > Hello! > > > > I've used a lot of time trying to get my custom Xen pv_ops dom0 kernel working with > > virt-install and/or virt-manager on Fedora 10, and now it seems I got things > > working. > > > > If you want to play with this you need: > > > > 1) New enough pv_ops dom0 kernel (2.6.29-rc8 or newer) so it has /sys/hypervisor support included > > - Compile with CONFIG_HIGHPTE=n since it seems to be broken still > > 2) libvirt 0.6.1 and related packages from Fedora 10 updates-testing > > > > In addition to those I'm using Xen 3.3.1-9 packages from rawhide/F11 rebuilt for F10. > > > > With the older Fedora 10 libvirt packages libvirtd was crashing often for me, and > > I had some other issues with virt-install console window not opening but stalling etc.. > > > > Today I was able to run the following on Fedora 10 32bit PAE pv_ops dom0: > > > > - CentOS 5.3 32bit PAE PV domU > > - Fedora 10 32bit PAE PV domU > > - Use virt-install to install Fedora 10 32bit PAE PV domU (using custom kickstart > > to force PAE kernel installation to avoid the anaconda BUG which installs > > wrong non-PAE kernel as a default). > > > > Fedora 11 (rawhide) installation most probably works too. > > FYI, I've just testing i686 and x86_64 Fedora 11 guest installs on a > RHEL5 Xen host and they both work flawlessly out of the box - including > a sane mouse pointer running in absolute, so no dual-cursor problems, > and installing correect PAE kernels > Replying to old thread.. today I tried installing F11 i386 domU with virt-install on centos 5.3 x86_64 dom0, and it doesn't seem to work.. The graphical VNC console doesn't show up, and it seems the domU kernel crashes. x86_64 domU installation on x86_64 dom0 seems to work though. Are you sure i386 on x86_64 worked for you? -- Pasi From berrange at redhat.com Mon Jul 27 21:45:06 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 27 Jul 2009 22:45:06 +0100 Subject: [fedora-virt] Success with Fedora 10 Xen pv_ops 2.6.29-rc8 dom0 In-Reply-To: <20090727213917.GZ24960@edu.joroinen.fi> References: <20090324192502.GS5528@edu.joroinen.fi> <20090324192846.GN19446@redhat.com> <20090727213917.GZ24960@edu.joroinen.fi> Message-ID: <20090727214506.GL15020@redhat.com> On Tue, Jul 28, 2009 at 12:39:17AM +0300, Pasi K?rkk?inen wrote: > On Tue, Mar 24, 2009 at 07:28:46PM +0000, Daniel P. Berrange wrote: > > On Tue, Mar 24, 2009 at 09:25:02PM +0200, Pasi K?rkk?inen wrote: > > > Hello! > > > > > > I've used a lot of time trying to get my custom Xen pv_ops dom0 kernel working with > > > virt-install and/or virt-manager on Fedora 10, and now it seems I got things > > > working. > > > > > > If you want to play with this you need: > > > > > > 1) New enough pv_ops dom0 kernel (2.6.29-rc8 or newer) so it has /sys/hypervisor support included > > > - Compile with CONFIG_HIGHPTE=n since it seems to be broken still > > > 2) libvirt 0.6.1 and related packages from Fedora 10 updates-testing > > > > > > In addition to those I'm using Xen 3.3.1-9 packages from rawhide/F11 rebuilt for F10. > > > > > > With the older Fedora 10 libvirt packages libvirtd was crashing often for me, and > > > I had some other issues with virt-install console window not opening but stalling etc.. > > > > > > Today I was able to run the following on Fedora 10 32bit PAE pv_ops dom0: > > > > > > - CentOS 5.3 32bit PAE PV domU > > > - Fedora 10 32bit PAE PV domU > > > - Use virt-install to install Fedora 10 32bit PAE PV domU (using custom kickstart > > > to force PAE kernel installation to avoid the anaconda BUG which installs > > > wrong non-PAE kernel as a default). > > > > > > Fedora 11 (rawhide) installation most probably works too. > > > > FYI, I've just testing i686 and x86_64 Fedora 11 guest installs on a > > RHEL5 Xen host and they both work flawlessly out of the box - including > > a sane mouse pointer running in absolute, so no dual-cursor problems, > > and installing correect PAE kernels > > > > Replying to old thread.. today I tried installing F11 i386 domU with > virt-install on centos 5.3 x86_64 dom0, and it doesn't seem to work.. > > The graphical VNC console doesn't show up, and it seems the domU kernel > crashes. > > x86_64 domU installation on x86_64 dom0 seems to work though. > Are you sure i386 on x86_64 worked for you? Yep, just checked my RHEL-5 box and it has this config name = "f11i686xen" uuid = "1417ac4b-bd9a-61cc-6faf-8e842cd72cb9" maxmem = 900 memory = 500 vcpus = 1 bootloader = "/usr/bin/pygrub" on_poweroff = "destroy" on_reboot = "restart" on_crash = "restart" vfb = [ "type=vnc,vncunused=1" ] disk = [ "tap:aio:/var/lib/xen/images/f11i686.img,xvda,w" ] vif = [ "mac=00:16:3e:71:38:63,bridge=xenbr0" ] And the guest disk is fully instlaled # ls -lhs /var/lib/xen/images/f11i686.img 3.4G -rwxr-xr-x 1 root root 5.1G Jun 4 06:33 /var/lib/xen/images/f11i686.img FWIW, the guest kernel here is 2.6.29-0.258.rc8.git2.fc11.i686.PAE So its possible things have changed since I did my install .... Also my x86_64 host only has 2 GB of RAM, so if there's any bugs with i686 guests at the >4GB phys RAM mark I wouldn't have seen them Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From pasik at iki.fi Mon Jul 27 22:11:11 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Tue, 28 Jul 2009 01:11:11 +0300 Subject: [fedora-virt] Fedora 10 and Fedora 11 Xen 32b domUs failing on x86_64 el5.3 dom0 In-Reply-To: <20090727214506.GL15020@redhat.com> References: <20090324192502.GS5528@edu.joroinen.fi> <20090324192846.GN19446@redhat.com> <20090727213917.GZ24960@edu.joroinen.fi> <20090727214506.GL15020@redhat.com> Message-ID: <20090727221111.GA24960@edu.joroinen.fi> On Mon, Jul 27, 2009 at 10:45:06PM +0100, Daniel P. Berrange wrote: > On Tue, Jul 28, 2009 at 12:39:17AM +0300, Pasi K?rkk?inen wrote: > > On Tue, Mar 24, 2009 at 07:28:46PM +0000, Daniel P. Berrange wrote: > > > On Tue, Mar 24, 2009 at 09:25:02PM +0200, Pasi K?rkk?inen wrote: > > > > Hello! > > > > > > > > I've used a lot of time trying to get my custom Xen pv_ops dom0 kernel working with > > > > virt-install and/or virt-manager on Fedora 10, and now it seems I got things > > > > working. > > > > > > > > If you want to play with this you need: > > > > > > > > 1) New enough pv_ops dom0 kernel (2.6.29-rc8 or newer) so it has /sys/hypervisor support included > > > > - Compile with CONFIG_HIGHPTE=n since it seems to be broken still > > > > 2) libvirt 0.6.1 and related packages from Fedora 10 updates-testing > > > > > > > > In addition to those I'm using Xen 3.3.1-9 packages from rawhide/F11 rebuilt for F10. > > > > > > > > With the older Fedora 10 libvirt packages libvirtd was crashing often for me, and > > > > I had some other issues with virt-install console window not opening but stalling etc.. > > > > > > > > Today I was able to run the following on Fedora 10 32bit PAE pv_ops dom0: > > > > > > > > - CentOS 5.3 32bit PAE PV domU > > > > - Fedora 10 32bit PAE PV domU > > > > - Use virt-install to install Fedora 10 32bit PAE PV domU (using custom kickstart > > > > to force PAE kernel installation to avoid the anaconda BUG which installs > > > > wrong non-PAE kernel as a default). > > > > > > > > Fedora 11 (rawhide) installation most probably works too. > > > > > > FYI, I've just testing i686 and x86_64 Fedora 11 guest installs on a > > > RHEL5 Xen host and they both work flawlessly out of the box - including > > > a sane mouse pointer running in absolute, so no dual-cursor problems, > > > and installing correect PAE kernels > > > > > > > Replying to old thread.. today I tried installing F11 i386 domU with > > virt-install on centos 5.3 x86_64 dom0, and it doesn't seem to work.. > > > > The graphical VNC console doesn't show up, and it seems the domU kernel > > crashes. > > > > x86_64 domU installation on x86_64 dom0 seems to work though. > > Are you sure i386 on x86_64 worked for you? > > Yep, just checked my RHEL-5 box and it has this config > > name = "f11i686xen" > uuid = "1417ac4b-bd9a-61cc-6faf-8e842cd72cb9" > maxmem = 900 > memory = 500 > vcpus = 1 > bootloader = "/usr/bin/pygrub" > on_poweroff = "destroy" > on_reboot = "restart" > on_crash = "restart" > vfb = [ "type=vnc,vncunused=1" ] > disk = [ "tap:aio:/var/lib/xen/images/f11i686.img,xvda,w" ] > vif = [ "mac=00:16:3e:71:38:63,bridge=xenbr0" ] > > Nothing weird here.. My guest has 1 vcpu aswell, and I'm using vnc. > And the guest disk is fully instlaled > > # ls -lhs /var/lib/xen/images/f11i686.img > 3.4G -rwxr-xr-x 1 root root 5.1G Jun 4 06:33 /var/lib/xen/images/f11i686.img > > > FWIW, the guest kernel here is 2.6.29-0.258.rc8.git2.fc11.i686.PAE > > So its possible things have changed since I did my install .... > Default kernel in Fedora 11 is: kernel-PAE-2.6.29.4-167.fc11.i686.rpm > Also my x86_64 host only has 2 GB of RAM, so if there's any bugs with > i686 guests at the >4GB phys RAM mark I wouldn't have seen them > My guests were using 512 MB and 1024 MB of RAM.. I tried again now, and yes, F10 and F11 i386 guests fail on CentOS 5.3 x86_64 dom0 with domU kernel crashes like this: http://pasik.reaktio.net/fedora/fedora10-32b-xen-domu-on-centos53-64b-dom0-install-crash.txt http://pasik.reaktio.net/fedora/fedora11-32b-xen-domu-on-centos53-64b-dom0-crash2.txt Checking if this processor honours the WP bit even in supervisor mode...Ok. 1 multicall(s) failed: cpu 0 Pid: 0, comm: swapper Not tainted 2.6.29.4-167.fc11.i686.PAE #1 Call Trace: [] ? printk+0x14/0x1d [] xen_mc_flush+0x12d/0x1f9 [] xen_mc_issue+0x19/0x4d [] xen_set_pud_hyper+0x79/0x81 [] xen_set_pud+0x8f/0x95 [] zap_low_mappings+0x2d/0x42 [] mem_init+0x2a0/0x2a8 [] start_kernel+0x264/0x313 [] i386_start_kernel+0x8c/0x97 [] xen_start_kernel+0x7f9/0x802 ------------[ cut here ]------------ kernel BUG at arch/x86/xen/multicalls.c:180! invalid opcode: 0000 [#1] SMP Hmm.. I wonder what's causing this. Can you test if it works for you? I used virt-install like this: virt-install --debug -n testvm -r 512 --vcpus=1 -f /dev/VolGroup00/testvm_disk --vnc -p -l "ftp://ftp.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/releases/11/Fedora/i386/os" The graphical VNC console newer shows up, and when I run "xm console testvm" I see that kernel crash. -- Pasi From pasik at iki.fi Mon Jul 27 22:39:26 2009 From: pasik at iki.fi (Pasi =?iso-8859-1?Q?K=E4rkk=E4inen?=) Date: Tue, 28 Jul 2009 01:39:26 +0300 Subject: [Fedora-xen] Re: [fedora-virt] Fedora 10 and Fedora 11 Xen 32b domUs failing on x86_64 el5.3 dom0 In-Reply-To: <20090727221111.GA24960@edu.joroinen.fi> References: <20090324192502.GS5528@edu.joroinen.fi> <20090324192846.GN19446@redhat.com> <20090727213917.GZ24960@edu.joroinen.fi> <20090727214506.GL15020@redhat.com> <20090727221111.GA24960@edu.joroinen.fi> Message-ID: <20090727223926.GB24960@edu.joroinen.fi> On Tue, Jul 28, 2009 at 01:11:11AM +0300, Pasi K?rkk?inen wrote: > On Mon, Jul 27, 2009 at 10:45:06PM +0100, Daniel P. Berrange wrote: > > On Tue, Jul 28, 2009 at 12:39:17AM +0300, Pasi K?rkk?inen wrote: > > > On Tue, Mar 24, 2009 at 07:28:46PM +0000, Daniel P. Berrange wrote: > > > > On Tue, Mar 24, 2009 at 09:25:02PM +0200, Pasi K?rkk?inen wrote: > > > > > Hello! > > > > > > > > > > I've used a lot of time trying to get my custom Xen pv_ops dom0 kernel working with > > > > > virt-install and/or virt-manager on Fedora 10, and now it seems I got things > > > > > working. > > > > > > > > > > If you want to play with this you need: > > > > > > > > > > 1) New enough pv_ops dom0 kernel (2.6.29-rc8 or newer) so it has /sys/hypervisor support included > > > > > - Compile with CONFIG_HIGHPTE=n since it seems to be broken still > > > > > 2) libvirt 0.6.1 and related packages from Fedora 10 updates-testing > > > > > > > > > > In addition to those I'm using Xen 3.3.1-9 packages from rawhide/F11 rebuilt for F10. > > > > > > > > > > With the older Fedora 10 libvirt packages libvirtd was crashing often for me, and > > > > > I had some other issues with virt-install console window not opening but stalling etc.. > > > > > > > > > > Today I was able to run the following on Fedora 10 32bit PAE pv_ops dom0: > > > > > > > > > > - CentOS 5.3 32bit PAE PV domU > > > > > - Fedora 10 32bit PAE PV domU > > > > > - Use virt-install to install Fedora 10 32bit PAE PV domU (using custom kickstart > > > > > to force PAE kernel installation to avoid the anaconda BUG which installs > > > > > wrong non-PAE kernel as a default). > > > > > > > > > > Fedora 11 (rawhide) installation most probably works too. > > > > > > > > FYI, I've just testing i686 and x86_64 Fedora 11 guest installs on a > > > > RHEL5 Xen host and they both work flawlessly out of the box - including > > > > a sane mouse pointer running in absolute, so no dual-cursor problems, > > > > and installing correect PAE kernels > > > > > > > > > > Replying to old thread.. today I tried installing F11 i386 domU with > > > virt-install on centos 5.3 x86_64 dom0, and it doesn't seem to work.. > > > > > > The graphical VNC console doesn't show up, and it seems the domU kernel > > > crashes. > > > > > > x86_64 domU installation on x86_64 dom0 seems to work though. > > > Are you sure i386 on x86_64 worked for you? > > > > Yep, just checked my RHEL-5 box and it has this config > > > > name = "f11i686xen" > > uuid = "1417ac4b-bd9a-61cc-6faf-8e842cd72cb9" > > maxmem = 900 > > memory = 500 > > vcpus = 1 > > bootloader = "/usr/bin/pygrub" > > on_poweroff = "destroy" > > on_reboot = "restart" > > on_crash = "restart" > > vfb = [ "type=vnc,vncunused=1" ] > > disk = [ "tap:aio:/var/lib/xen/images/f11i686.img,xvda,w" ] > > vif = [ "mac=00:16:3e:71:38:63,bridge=xenbr0" ] > > > > > > Nothing weird here.. My guest has 1 vcpu aswell, and I'm using vnc. > > > And the guest disk is fully instlaled > > > > # ls -lhs /var/lib/xen/images/f11i686.img > > 3.4G -rwxr-xr-x 1 root root 5.1G Jun 4 06:33 /var/lib/xen/images/f11i686.img > > > > > > FWIW, the guest kernel here is 2.6.29-0.258.rc8.git2.fc11.i686.PAE > > > > So its possible things have changed since I did my install .... > > > > Default kernel in Fedora 11 is: kernel-PAE-2.6.29.4-167.fc11.i686.rpm > > > Also my x86_64 host only has 2 GB of RAM, so if there's any bugs with > > i686 guests at the >4GB phys RAM mark I wouldn't have seen them > > > > My guests were using 512 MB and 1024 MB of RAM.. > > I tried again now, and yes, F10 and F11 i386 guests fail on CentOS 5.3 > x86_64 dom0 with domU kernel crashes like this: > > http://pasik.reaktio.net/fedora/fedora10-32b-xen-domu-on-centos53-64b-dom0-install-crash.txt > http://pasik.reaktio.net/fedora/fedora11-32b-xen-domu-on-centos53-64b-dom0-crash2.txt > > > Checking if this processor honours the WP bit even in supervisor mode...Ok. > 1 multicall(s) failed: cpu 0 > Pid: 0, comm: swapper Not tainted 2.6.29.4-167.fc11.i686.PAE #1 > Call Trace: > [] ? printk+0x14/0x1d > [] xen_mc_flush+0x12d/0x1f9 > [] xen_mc_issue+0x19/0x4d > [] xen_set_pud_hyper+0x79/0x81 > [] xen_set_pud+0x8f/0x95 > [] zap_low_mappings+0x2d/0x42 > [] mem_init+0x2a0/0x2a8 > [] start_kernel+0x264/0x313 > [] i386_start_kernel+0x8c/0x97 > [] xen_start_kernel+0x7f9/0x802 > ------------[ cut here ]------------ > kernel BUG at arch/x86/xen/multicalls.c:180! > invalid opcode: 0000 [#1] SMP > > Hmm.. I wonder what's causing this. > > Can you test if it works for you? > > I used virt-install like this: > virt-install --debug -n testvm -r 512 --vcpus=1 -f /dev/VolGroup00/testvm_disk --vnc -p -l "ftp://ftp.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/releases/11/Fedora/i386/os" > > The graphical VNC console newer shows up, and when I run "xm console testvm" > I see that kernel crash. > Actually I think I just figured it out.. It's this RHEL5 bug: https://bugzilla.redhat.com/show_bug.cgi?id=467698 I upgraded kernel+xen to -159.el5 and now both F10 and F11 32b domUs work and install OK on x86_64 host/dom0. -- Pasi From berrange at redhat.com Mon Jul 27 22:46:04 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Mon, 27 Jul 2009 23:46:04 +0100 Subject: [Fedora-xen] Re: [fedora-virt] Fedora 10 and Fedora 11 Xen 32b domUs failing on x86_64 el5.3 dom0 In-Reply-To: <20090727223926.GB24960@edu.joroinen.fi> References: <20090324192502.GS5528@edu.joroinen.fi> <20090324192846.GN19446@redhat.com> <20090727213917.GZ24960@edu.joroinen.fi> <20090727214506.GL15020@redhat.com> <20090727221111.GA24960@edu.joroinen.fi> <20090727223926.GB24960@edu.joroinen.fi> Message-ID: <20090727224604.GA31783@redhat.com> On Tue, Jul 28, 2009 at 01:39:26AM +0300, Pasi K?rkk?inen wrote: > On Tue, Jul 28, 2009 at 01:11:11AM +0300, Pasi K?rkk?inen wrote: > > On Mon, Jul 27, 2009 at 10:45:06PM +0100, Daniel P. Berrange wrote: > > > On Tue, Jul 28, 2009 at 12:39:17AM +0300, Pasi K?rkk?inen wrote: > > > > x86_64 domU installation on x86_64 dom0 seems to work though. > > > > Are you sure i386 on x86_64 worked for you? > > > > > > Yep, just checked my RHEL-5 box and it has this config > > > > > > name = "f11i686xen" > > > uuid = "1417ac4b-bd9a-61cc-6faf-8e842cd72cb9" > > > maxmem = 900 > > > memory = 500 > > > vcpus = 1 > > > bootloader = "/usr/bin/pygrub" > > > on_poweroff = "destroy" > > > on_reboot = "restart" > > > on_crash = "restart" > > > vfb = [ "type=vnc,vncunused=1" ] > > > disk = [ "tap:aio:/var/lib/xen/images/f11i686.img,xvda,w" ] > > > vif = [ "mac=00:16:3e:71:38:63,bridge=xenbr0" ] > > > > > > > > > > Nothing weird here.. My guest has 1 vcpu aswell, and I'm using vnc. > > > > > And the guest disk is fully instlaled > > > > > > # ls -lhs /var/lib/xen/images/f11i686.img > > > 3.4G -rwxr-xr-x 1 root root 5.1G Jun 4 06:33 /var/lib/xen/images/f11i686.img > > > > > > > > > FWIW, the guest kernel here is 2.6.29-0.258.rc8.git2.fc11.i686.PAE > > > > > > So its possible things have changed since I did my install .... > > > > > > > Default kernel in Fedora 11 is: kernel-PAE-2.6.29.4-167.fc11.i686.rpm > > > > > Also my x86_64 host only has 2 GB of RAM, so if there's any bugs with > > > i686 guests at the >4GB phys RAM mark I wouldn't have seen them > > > > > > > My guests were using 512 MB and 1024 MB of RAM.. > > > > I tried again now, and yes, F10 and F11 i386 guests fail on CentOS 5.3 > > x86_64 dom0 with domU kernel crashes like this: > > > > http://pasik.reaktio.net/fedora/fedora10-32b-xen-domu-on-centos53-64b-dom0-install-crash.txt > > http://pasik.reaktio.net/fedora/fedora11-32b-xen-domu-on-centos53-64b-dom0-crash2.txt > > > > > > Checking if this processor honours the WP bit even in supervisor mode...Ok. > > 1 multicall(s) failed: cpu 0 > > Pid: 0, comm: swapper Not tainted 2.6.29.4-167.fc11.i686.PAE #1 > > Call Trace: > > [] ? printk+0x14/0x1d > > [] xen_mc_flush+0x12d/0x1f9 > > [] xen_mc_issue+0x19/0x4d > > [] xen_set_pud_hyper+0x79/0x81 > > [] xen_set_pud+0x8f/0x95 > > [] zap_low_mappings+0x2d/0x42 > > [] mem_init+0x2a0/0x2a8 > > [] start_kernel+0x264/0x313 > > [] i386_start_kernel+0x8c/0x97 > > [] xen_start_kernel+0x7f9/0x802 > > ------------[ cut here ]------------ > > kernel BUG at arch/x86/xen/multicalls.c:180! > > invalid opcode: 0000 [#1] SMP > > > > Hmm.. I wonder what's causing this. > > > > Can you test if it works for you? > > > > I used virt-install like this: > > virt-install --debug -n testvm -r 512 --vcpus=1 -f /dev/VolGroup00/testvm_disk --vnc -p -l "ftp://ftp.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/releases/11/Fedora/i386/os" > > > > The graphical VNC console newer shows up, and when I run "xm console testvm" > > I see that kernel crash. > > > > Actually I think I just figured it out.. > > It's this RHEL5 bug: https://bugzilla.redhat.com/show_bug.cgi?id=467698 Ah yes, I probably had a internal 5.3 snapshot kernel installed which would have that fix Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From markmc at redhat.com Tue Jul 28 08:30:17 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 09:30:17 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1247763853.3038.105.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> Message-ID: <1248769817.3089.20.camel@blaa> Hi, The test packages at http://markmc.fedorapeople.org/virt-preview/: == libvirt == * Mon Jul 27 2009 Daniel Veillard - 0.7.0-0.1.gitf055724 - prerelease of 0.7.0 * Sat Jul 25 2009 Fedora Release Engineering - 0.6.5-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild * Fri Jul 10 2009 Richard W.M. Jones - 0.6.5-2.fc12 - Bump release number to rebuild against new libparted. == qemu == * Sun Jul 26 2009 Fedora Release Engineering - 2:0.10.50-14.kvm88 - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild * Thu Jul 23 2009 Glauber Costa - 2:0.10.50-13.kvm88 - Fix bug 513249, -net channel option is broken * Thu Jul 16 2009 Daniel P. Berrange - 2:0.10.50-12.kvm88 - Add 'qemu' user and group accounts - Force disable xen until it can be made to build Cheers, Mark. From markmc at redhat.com Tue Jul 28 08:55:53 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 09:55:53 +0100 Subject: [fedora-virt] git tree for Fedora qemu patches In-Reply-To: <1245862194.29350.5.camel@blaa> References: <1245862194.29350.5.camel@blaa> Message-ID: <1248771353.3089.21.camel@blaa> On Wed, 2009-06-24 at 16:49 +0000, Mark McLoughlin wrote: > Hey, > Glauber and I are going to start using git to manage the patches for > the qemu package. The idea is that we'll use git's magical powers to > make it easier for us to fix problems in patches, cherry-pick patches > from upstream, re-base our patches to a newer upstream, etc. > > Nothing is changing, really - patches should still go upstream first > and we'll still include patches as individual files in the source RPM - > this is purely about making managing those patches easier. > > Here's the tree: > > http://git.et.redhat.com/?p=qemu-fedora.git > > It might be useful to others who want to help with back-porting fixes > etc. I've just written up how to use it here: https://fedoraproject.org/wiki/Maintaining_QEMU_patches Cheers, Mark. From giallu at gmail.com Tue Jul 28 10:24:00 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Tue, 28 Jul 2009 12:24:00 +0200 Subject: [fedora-virt] Can't use network in guests Message-ID: Hi all, it seems that after I installed Fedora 11 I can't assign to guests any ethernet device; in particular, the virt-manager VM creation wizard do not let me choose any network device, and if I try to assign it later via the "Add new hardware" button I get a traceback: Traceback (most recent call last): File "/usr/share/virt-manager/virtManager/addhardware.py", line 288, in forward if(self.validate(notebook.get_current_page()) != True): File "/usr/share/virt-manager/virtManager/addhardware.py", line 882, in validate net = self.get_config_network() File "/usr/share/virt-manager/virtManager/addhardware.py", line 407, in get_config_network return ["network", model.get_value(net.get_active_iter(), 0)] TypeError: iter must be a GtkTreeIter any idea? -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From markmc at redhat.com Tue Jul 28 10:25:32 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 11:25:32 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248769817.3089.20.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> Message-ID: <1248776732.3089.45.camel@blaa> Thanks to Jan Ondrej for noticing, virt-preview is updated with this libvirt broken deps fix: * Tue Jul 28 2009 Mark McLoughlin - 0.7.0-0.2.gitf055724 - Drop glusterfs dep to 2.0.1 (bug #514191) Cheers, Mark. From markmc at redhat.com Tue Jul 28 10:29:08 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 11:29:08 +0100 Subject: [fedora-virt] Can't use network in guests In-Reply-To: References: Message-ID: <1248776948.3089.48.camel@blaa> On Tue, 2009-07-28 at 12:24 +0200, Gianluca Sforna wrote: > Hi all, > it seems that after I installed Fedora 11 I can't assign to guests any > ethernet device; in particular, the virt-manager VM creation wizard do > not let me choose any network device, and if I try to assign it later > via the "Add new hardware" button I get a traceback: > > Traceback (most recent call last): > File "/usr/share/virt-manager/virtManager/addhardware.py", line 288, > in forward > if(self.validate(notebook.get_current_page()) != True): > File "/usr/share/virt-manager/virtManager/addhardware.py", line 882, > in validate > net = self.get_config_network() > File "/usr/share/virt-manager/virtManager/addhardware.py", line 407, > in get_config_network > return ["network", model.get_value(net.get_active_iter(), 0)] > TypeError: iter must be a GtkTreeIter That certainly looks like a virt-manager bug, please do file it in bugzilla. Can you use 'virsh edit' to add e.g.: See also: http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging https://fedoraproject.org/wiki/Reporting_virtualization_bugs#Networking Cheers, Mark. From giallu at gmail.com Tue Jul 28 10:58:35 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Tue, 28 Jul 2009 12:58:35 +0200 Subject: [fedora-virt] Can't use network in guests In-Reply-To: <1248776948.3089.48.camel@blaa> References: <1248776948.3089.48.camel@blaa> Message-ID: On Tue, Jul 28, 2009 at 12:29 PM, Mark McLoughlin wrote: > > Can you use 'virsh edit' to add e.g.: > > ? ? > ? ? ? > ? ? ? > ? ? This leads to another traceback when starting the VM: Traceback (most recent call last): File "/usr/share/virt-manager/virtManager/engine.py", line 493, in run_domain vm.startup() File "/usr/share/virt-manager/virtManager/domain.py", line 573, in startup self.vm.create() File "/usr/lib64/python2.6/site-packages/libvirt.py", line 287, in create if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self) libvirtError: internal error Failed to add tap interface 'vnet%d' to bridge 'br0' : No such device > > See also: > > ?http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging > ?https://fedoraproject.org/wiki/Reporting_virtualization_bugs#Networking Thanks for the pointers, I found this suspicious message in virt-manager.log: [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (proxies:400) Introspect error on :1.1:/org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7: dbus.exceptions.DBusException: No device with id /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] DEBUG (proxies:403) Executing introspect queue due to error [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (connection:218) Exception in handler for D-Bus signal: Traceback (most recent call last): File "/usr/lib/python2.6/site-packages/dbus/connection.py", line 214, in maybe_handle_message self._handler(*args, **kwargs) File "/usr/share/virt-manager/virtManager/connection.py", line 170, in _net_phys_device_added if objif.QueryCapability("net"): File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 68, in __call__ return self._proxy_method(*args, **keywords) File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 140, in __call__ **keywords) File "/usr/lib/python2.6/site-packages/dbus/connection.py", line 630, in call_blocking message, timeout) DBusException: org.freedesktop.Hal.NoSuchDevice: No device with id /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 still confused... -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From markmc at redhat.com Tue Jul 28 11:20:44 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 12:20:44 +0100 Subject: [fedora-virt] Can't use network in guests In-Reply-To: References: <1248776948.3089.48.camel@blaa> Message-ID: <1248780044.3089.59.camel@blaa> On Tue, 2009-07-28 at 12:58 +0200, Gianluca Sforna wrote: > On Tue, Jul 28, 2009 at 12:29 PM, Mark McLoughlin wrote: > > > > Can you use 'virsh edit' to add e.g.: > > > > > > > > > > > > This leads to another traceback when starting the VM: Did you file a bug with the first traceback? > Traceback (most recent call last): > File "/usr/share/virt-manager/virtManager/engine.py", line 493, in run_domain > vm.startup() > File "/usr/share/virt-manager/virtManager/domain.py", line 573, in startup > self.vm.create() > File "/usr/lib64/python2.6/site-packages/libvirt.py", line 287, in create > if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self) > libvirtError: internal error Failed to add tap interface 'vnet%d' to > bridge 'br0' : No such device What exactly is the guest's configuration? Is 'vnet%d' mentioned anywhere? What version of libvirt? > > See also: > > > > http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging > > https://fedoraproject.org/wiki/Reporting_virtualization_bugs#Networking > > Thanks for the pointers, I found this suspicious message in virt-manager.log: > > [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (proxies:400) > Introspect error on > :1.1:/org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7: > dbus.exceptions.DBusException: No device with id > /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 > [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] DEBUG (proxies:403) > Executing introspect queue due to error > [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (connection:218) > Exception in handler for D-Bus signal: > Traceback (most recent call last): > File "/usr/lib/python2.6/site-packages/dbus/connection.py", line > 214, in maybe_handle_message > self._handler(*args, **kwargs) > File "/usr/share/virt-manager/virtManager/connection.py", line 170, > in _net_phys_device_added > if objif.QueryCapability("net"): > File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 68, in __call__ > return self._proxy_method(*args, **keywords) > File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 140, in __call__ > **keywords) > File "/usr/lib/python2.6/site-packages/dbus/connection.py", line > 630, in call_blocking > message, timeout) > DBusException: org.freedesktop.Hal.NoSuchDevice: No device with id > /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 > > still confused... Odd, dbus telling us a device has added and then failing to find it. Seen this one before Cole? Cheers, Mark. From hbrock at redhat.com Tue Jul 28 11:21:36 2009 From: hbrock at redhat.com (Hugh O. Brock) Date: Tue, 28 Jul 2009 07:21:36 -0400 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248769817.3089.20.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> Message-ID: <20090728112135.GA13765@redhat.com> On Tue, Jul 28, 2009 at 09:30:17AM +0100, Mark McLoughlin wrote: > Hi, > > The test packages at http://markmc.fedorapeople.org/virt-preview/: > > == libvirt == > > * Mon Jul 27 2009 Daniel Veillard - 0.7.0-0.1.gitf055724 > - prerelease of 0.7.0 > > * Sat Jul 25 2009 Fedora Release Engineering - 0.6.5-3 > - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild > > * Fri Jul 10 2009 Richard W.M. Jones - 0.6.5-2.fc12 > - Bump release number to rebuild against new libparted. > > == qemu == > > * Sun Jul 26 2009 Fedora Release Engineering - 2:0.10.50-14.kvm88 > - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild > > * Thu Jul 23 2009 Glauber Costa - 2:0.10.50-13.kvm88 > - Fix bug 513249, -net channel option is broken > > * Thu Jul 16 2009 Daniel P. Berrange - 2:0.10.50-12.kvm88 > - Add 'qemu' user and group accounts > - Force disable xen until it can be made to build > > Cheers, > Mark. Hey Mark. This version of libvirt is going to have a dependency on netcf, which is I think only in Rawhide at the moment -- Do we want to pull it into virt-preview as well? --Hugh From markmc at redhat.com Tue Jul 28 11:30:04 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 12:30:04 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <20090728112135.GA13765@redhat.com> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728112135.GA13765@redhat.com> Message-ID: <1248780604.3089.60.camel@blaa> On Tue, 2009-07-28 at 07:21 -0400, Hugh O. Brock wrote: > On Tue, Jul 28, 2009 at 09:30:17AM +0100, Mark McLoughlin wrote: > > Hi, > > > > The test packages at http://markmc.fedorapeople.org/virt-preview/: > > > > == libvirt == > > > > * Mon Jul 27 2009 Daniel Veillard - 0.7.0-0.1.gitf055724 > > - prerelease of 0.7.0 > > > > * Sat Jul 25 2009 Fedora Release Engineering - 0.6.5-3 > > - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild > > > > * Fri Jul 10 2009 Richard W.M. Jones - 0.6.5-2.fc12 > > - Bump release number to rebuild against new libparted. > > > > == qemu == > > > > * Sun Jul 26 2009 Fedora Release Engineering - 2:0.10.50-14.kvm88 > > - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild > > > > * Thu Jul 23 2009 Glauber Costa - 2:0.10.50-13.kvm88 > > - Fix bug 513249, -net channel option is broken > > > > * Thu Jul 16 2009 Daniel P. Berrange - 2:0.10.50-12.kvm88 > > - Add 'qemu' user and group accounts > > - Force disable xen until it can be made to build > > > > Cheers, > > Mark. > > Hey Mark. This version of libvirt is going to have a dependency on > netcf, which is I think only in Rawhide at the moment -- Do we want to > pull it into virt-preview as well? Yep, can do - so long as it won't require anything else rawhide specific? Cheers, Mark. From markmc at redhat.com Tue Jul 28 11:33:50 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 12:33:50 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248780604.3089.60.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728112135.GA13765@redhat.com> <1248780604.3089.60.camel@blaa> Message-ID: <1248780830.3089.62.camel@blaa> On Tue, 2009-07-28 at 12:30 +0100, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 07:21 -0400, Hugh O. Brock wrote: > > Hey Mark. This version of libvirt is going to have a dependency on > > netcf, which is I think only in Rawhide at the moment -- Do we want to > > pull it into virt-preview as well? > > Yep, can do - so long as it won't require anything else rawhide > specific? Sorry, brainfart. We can't build things in virt-preview that aren't in dist-f11-updates, so we'd have to disable netcf for now >From CVS, it looks like lutter is going to push it to F-11, though? Cheers, Mark. From crobinso at redhat.com Tue Jul 28 12:39:00 2009 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 28 Jul 2009 08:39:00 -0400 Subject: [fedora-virt] Can't use network in guests In-Reply-To: <1248780044.3089.59.camel@blaa> References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> Message-ID: <4A6EF164.4050404@redhat.com> Mark McLoughlin wrote: > On Tue, 2009-07-28 at 12:58 +0200, Gianluca Sforna wrote: >> On Tue, Jul 28, 2009 at 12:29 PM, Mark McLoughlin wrote: >>> Can you use 'virsh edit' to add e.g.: >>> >>> >>> >>> >>> >> This leads to another traceback when starting the VM: > > Did you file a bug with the first traceback? > >> Traceback (most recent call last): >> File "/usr/share/virt-manager/virtManager/engine.py", line 493, in run_domain >> vm.startup() >> File "/usr/share/virt-manager/virtManager/domain.py", line 573, in startup >> self.vm.create() >> File "/usr/lib64/python2.6/site-packages/libvirt.py", line 287, in create >> if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self) >> libvirtError: internal error Failed to add tap interface 'vnet%d' to >> bridge 'br0' : No such device > > What exactly is the guest's configuration? Is 'vnet%d' mentioned > anywhere? What version of libvirt? > >>> See also: >>> >>> http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging >>> https://fedoraproject.org/wiki/Reporting_virtualization_bugs#Networking >> Thanks for the pointers, I found this suspicious message in virt-manager.log: >> >> [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (proxies:400) >> Introspect error on >> :1.1:/org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7: >> dbus.exceptions.DBusException: No device with id >> /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 >> [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] DEBUG (proxies:403) >> Executing introspect queue due to error >> [Tue, 28 Jul 2009 12:54:16 virt-manager 3653] ERROR (connection:218) >> Exception in handler for D-Bus signal: >> Traceback (most recent call last): >> File "/usr/lib/python2.6/site-packages/dbus/connection.py", line >> 214, in maybe_handle_message >> self._handler(*args, **kwargs) >> File "/usr/share/virt-manager/virtManager/connection.py", line 170, >> in _net_phys_device_added >> if objif.QueryCapability("net"): >> File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 68, in __call__ >> return self._proxy_method(*args, **keywords) >> File "/usr/lib/python2.6/site-packages/dbus/proxies.py", line 140, in __call__ >> **keywords) >> File "/usr/lib/python2.6/site-packages/dbus/connection.py", line >> 630, in call_blocking >> message, timeout) >> DBusException: org.freedesktop.Hal.NoSuchDevice: No device with id >> /org/freedesktop/Hal/devices/net_d2_eb_bc_ff_01_a7 >> >> still confused... > > Odd, dbus telling us a device has added and then failing to find it. > Seen this one before Cole? > I don't think so. Filing a bug with both those tracebacks would be best. Thanks, Cole From hbrock at redhat.com Tue Jul 28 13:00:26 2009 From: hbrock at redhat.com (Hugh O. Brock) Date: Tue, 28 Jul 2009 09:00:26 -0400 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248780830.3089.62.camel@blaa> References: <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728112135.GA13765@redhat.com> <1248780604.3089.60.camel@blaa> <1248780830.3089.62.camel@blaa> Message-ID: <20090728130026.GB13765@redhat.com> On Tue, Jul 28, 2009 at 12:33:50PM +0100, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 12:30 +0100, Mark McLoughlin wrote: > > On Tue, 2009-07-28 at 07:21 -0400, Hugh O. Brock wrote: > > > Hey Mark. This version of libvirt is going to have a dependency on > > > netcf, which is I think only in Rawhide at the moment -- Do we want to > > > pull it into virt-preview as well? > > > > Yep, can do - so long as it won't require anything else rawhide > > specific? > > Sorry, brainfart. > > We can't build things in virt-preview that aren't in dist-f11-updates, > so we'd have to disable netcf for now > > >From CVS, it looks like lutter is going to push it to F-11, though? Hmm, yes, and in point of fact since it's a brand-new package it might as well go into updates-testing and (eventually) stable. So probably no need to put it in virt-preview in that case. On the other hand, next time there's a major update for f12... Take care, --Hugh From giallu at gmail.com Tue Jul 28 13:40:11 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Tue, 28 Jul 2009 15:40:11 +0200 Subject: [fedora-virt] Can't use network in guests In-Reply-To: <4A6EF164.4050404@redhat.com> References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> Message-ID: On Tue, Jul 28, 2009 at 1:20 PM, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 12:58 +0200, Gianluca Sforna wrote: >> On Tue, Jul 28, 2009 at 12:29 PM, Mark McLoughlin wrote: >> > >> > Can you use 'virsh edit' to add e.g.: >> > >> > >> > >> > >> > >> >> This leads to another traceback when starting the VM: > > Did you file a bug with the first traceback? I just did it: https://bugzilla.redhat.com/show_bug.cgi?id=514228 > >> Traceback (most recent call last): >> File "/usr/share/virt-manager/virtManager/engine.py", line 493, in run_domain >> vm.startup() >> File "/usr/share/virt-manager/virtManager/domain.py", line 573, in startup >> self.vm.create() >> File "/usr/lib64/python2.6/site-packages/libvirt.py", line 287, in create >> if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self) >> libvirtError: internal error Failed to add tap interface 'vnet%d' to >> bridge 'br0' : No such device > > What exactly is the guest's configuration? Is 'vnet%d' mentioned > anywhere? What version of libvirt? libvirt-0.6.2-13.fc11.x86_64 test 13f7c43f-de93-4836-74b7-97b6796fae42 1048576 1048576 1 hvm destroy restart restart /usr/bin/qemu-kvm -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From lutter at redhat.com Tue Jul 28 13:44:20 2009 From: lutter at redhat.com (David Lutterkort) Date: Tue, 28 Jul 2009 13:44:20 +0000 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248780830.3089.62.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728112135.GA13765@redhat.com> <1248780604.3089.60.camel@blaa> <1248780830.3089.62.camel@blaa> Message-ID: <1248788660.4006.44.camel@localhost.localdomain> On Tue, 2009-07-28 at 12:33 +0100, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 12:30 +0100, Mark McLoughlin wrote: > > On Tue, 2009-07-28 at 07:21 -0400, Hugh O. Brock wrote: > > > Hey Mark. This version of libvirt is going to have a dependency on > > > netcf, which is I think only in Rawhide at the moment -- Do we want to > > > pull it into virt-preview as well? > > > > Yep, can do - so long as it won't require anything else rawhide > > specific? > > Sorry, brainfart. > > We can't build things in virt-preview that aren't in dist-f11-updates, > so we'd have to disable netcf for now > > >From CVS, it looks like lutter is going to push it to F-11, though? Yes, I am building it for F-10 and F-11 - the delay is caused by the dependency on augeas >= 0.5.2, which is not in updates yet, only updates-testing, but I had releng tag it as an override. IOW, netcf should be in updates-testing for F-10 and F-11 shortly. David From berrange at redhat.com Tue Jul 28 13:46:34 2009 From: berrange at redhat.com (Daniel P. Berrange) Date: Tue, 28 Jul 2009 14:46:34 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248780830.3089.62.camel@blaa> References: <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728112135.GA13765@redhat.com> <1248780604.3089.60.camel@blaa> <1248780830.3089.62.camel@blaa> Message-ID: <20090728134634.GB11885@redhat.com> On Tue, Jul 28, 2009 at 12:33:50PM +0100, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 12:30 +0100, Mark McLoughlin wrote: > > On Tue, 2009-07-28 at 07:21 -0400, Hugh O. Brock wrote: > > > Hey Mark. This version of libvirt is going to have a dependency on > > > netcf, which is I think only in Rawhide at the moment -- Do we want to > > > pull it into virt-preview as well? > > > > Yep, can do - so long as it won't require anything else rawhide > > specific? > > Sorry, brainfart. > > We can't build things in virt-preview that aren't in dist-f11-updates, > so we'd have to disable netcf for now Can't you just do a local mock based build instead of koji scratch ? We only really need to support x86_64 & i386 for virt-preview, so lack of ppc coverage wouldn't really matter Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| From markmc at redhat.com Tue Jul 28 14:13:35 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 15:13:35 +0100 Subject: [fedora-virt] Can't use network in guests In-Reply-To: References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> Message-ID: <1248790415.3089.65.camel@blaa> On Tue, 2009-07-28 at 15:40 +0200, Gianluca Sforna wrote: > On Tue, Jul 28, 2009 at 1:20 PM, Mark McLoughlin wrote: > > On Tue, 2009-07-28 at 12:58 +0200, Gianluca Sforna wrote: > >> On Tue, Jul 28, 2009 at 12:29 PM, Mark McLoughlin wrote: > >> > > >> > Can you use 'virsh edit' to add e.g.: > >> > > >> > > >> > > >> > > >> > > >> > >> This leads to another traceback when starting the VM: > > > > Did you file a bug with the first traceback? > > I just did it: > https://bugzilla.redhat.com/show_bug.cgi?id=514228 Thanks. > >> Traceback (most recent call last): > >> File "/usr/share/virt-manager/virtManager/engine.py", line 493, in run_domain > >> vm.startup() > >> File "/usr/share/virt-manager/virtManager/domain.py", line 573, in startup > >> self.vm.create() > >> File "/usr/lib64/python2.6/site-packages/libvirt.py", line 287, in create > >> if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self) > >> libvirtError: internal error Failed to add tap interface 'vnet%d' to > >> bridge 'br0' : No such device > > > > What exactly is the guest's configuration? Is 'vnet%d' mentioned > > anywhere? What version of libvirt? > > libvirt-0.6.2-13.fc11.x86_64 > > > test > 13f7c43f-de93-4836-74b7-97b6796fae42 > 1048576 > 1048576 > 1 > > hvm > > > > > > > > > destroy > restart > restart > > /usr/bin/qemu-kvm > > > > > > > > > > > > Try deleting this line Cheers, Mark. From giallu at gmail.com Tue Jul 28 14:35:43 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Tue, 28 Jul 2009 16:35:43 +0200 Subject: [fedora-virt] Can't use network in guests In-Reply-To: <1248790415.3089.65.camel@blaa> References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> <1248790415.3089.65.camel@blaa> Message-ID: On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: >> ? ? >> ? ? ? >> ? ? ? >> ? ? ? > > Try deleting this line I tried removing the line with virsh edit, but restarting the VM with virsh start leads to the same error. I double checked and the line appeared again, I've no idea how it got there again... -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From rich at lat.com Tue Jul 28 15:48:50 2009 From: rich at lat.com (Rich Mahn) Date: Tue, 28 Jul 2009 11:48:50 -0400 Subject: [fedora-virt] Can't use network in guests In-Reply-To: Your message of "Tue, 28 Jul 2009 16:35:43 +0200." Message-ID: <200907281548.n6SFmoHj023833@raspberry.lat.com> > On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: > >> ?? ?? > >> ?? ?? ?? > >> ?? ?? ?? > >> ?? ?? ?? > > > > Try deleting this line > I tried removing the line with virsh edit, but restarting the VM with > virsh start leads to the same error. I double checked and the line > appeared again, I've no idea how it got there again... I've just gone through similar situations and now have everything working like I want. One of many problems I had was the one above (and I'm not sure which thing I did fixed it.) So here's some ideas: 1. Make sure you aren't using NetworkManager. It seems to do unexpected things automatically, and according to http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging is doesn't support bridging as of F9. The instructions at that URL pretty much gave me everything I needed to get things going. 2. When I set my interface as you have (mac address and soruce bridge only) it adds a target dev=vnet0 automatically. And this works. 3. You might need to update some packages. On the client I was unable to make NIS work until I updated the ypbind package. Good luck. Rich From rich at lat.com Tue Jul 28 15:36:09 2009 From: rich at lat.com (Rich Mahn) Date: Tue, 28 Jul 2009 11:36:09 -0400 Subject: [fedora-virt] Can't use network in guests In-Reply-To: Your message of "Tue, 28 Jul 2009 16:35:43 +0200." Message-ID: <200907281536.n6SFa9qX023372@raspberry.lat.com> > On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: > >> ?? ?? > >> ?? ?? ?? > >> ?? ?? ?? > >> ?? ?? ?? > > > > Try deleting this line > I tried removing the line with virsh edit, but restarting the VM with > virsh start leads to the same error. I double checked and the line > appeared again, I've no idea how it got there again... I've just gone through similar situations and now have everything working like I want. One of many problems I had was the one above (and I'm not sure which thing I did fixed it.) So here's some ideas: 1. Make sure you aren't using NetworkManager. It seems to do unexpected things automatically, and according to http://wiki.libvirt.org/page/Networking#Fedora.2FRHEL_Bridging is doesn't support bridging as of F9. The instructions at that URL pretty much gave me everything I needed to get things going. 2. When I set my interface as you have (mac address and soruce bridge only) it adds a target dev=vnet0 automatically. And this works. 3. You might need to update some packages. On the client I was unable to make NIS work until I updated the ypbind package. Good luck. Rich From rjones at redhat.com Tue Jul 28 18:15:22 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 28 Jul 2009 19:15:22 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248769817.3089.20.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> Message-ID: <20090728181522.GA17223@amd.home.annexia.org> On Tue, Jul 28, 2009 at 09:30:17AM +0100, Mark McLoughlin wrote: > == qemu == > > * Sun Jul 26 2009 Fedora Release Engineering - 2:0.10.50-14.kvm88 > - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild This version of qemu is randomly broken when running libguestfs ... > * Thu Jul 23 2009 Glauber Costa - 2:0.10.50-13.kvm88 > - Fix bug 513249, -net channel option is broken ... even with this patch (which fixes guestfwd support). It seems like a qemu-TCG-on-Xen problem (yet again). Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Tue Jul 28 18:16:01 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 28 Jul 2009 19:16:01 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <20090728181522.GA17223@amd.home.annexia.org> References: <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728181522.GA17223@amd.home.annexia.org> Message-ID: <20090728181601.GA18139@amd.home.annexia.org> On Tue, Jul 28, 2009 at 07:15:22PM +0100, Richard W.M. Jones wrote: > It seems like a qemu-TCG-on-Xen problem (yet again). I wasn't just complaining about this - I'm going to try to track down the emulation bug when I have some time. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into Xen guests. http://et.redhat.com/~rjones/virt-p2v From rjones at redhat.com Tue Jul 28 18:21:40 2009 From: rjones at redhat.com (Richard W.M. Jones) Date: Tue, 28 Jul 2009 19:21:40 +0100 Subject: [fedora-virt] Can't use network in guests In-Reply-To: References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> <1248790415.3089.65.camel@blaa> Message-ID: <20090728182140.GB17223@amd.home.annexia.org> On Tue, Jul 28, 2009 at 04:35:43PM +0200, Gianluca Sforna wrote: > On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: > >> ? ? > >> ? ? ? > >> ? ? ? > >> ? ? ? > > > > Try deleting this line > > I tried removing the line with virsh edit, but restarting the VM with > virsh start leads to the same error. I double checked and the line > appeared again, I've no idea how it got there again... 'virsh edit' isn't editing a simple configuration file, that's why. When the domain is running, it asks libvirt to create an XML representation of the domain running domain (from libvirtd's internal data structures), which it edits, then that is parsed back by libvirt into some internal structures. When the domain is inactive, ... actually I know it uses a different path, but I'm not sure what precisely happens with KVM guests, but Dan will be able to tell us all. Anyway there is plenty of scope for edits to go strangely. Rich. -- Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones virt-df lists disk usage of guests without needing to install any software inside the virtual machine. Supports Linux and Windows. http://et.redhat.com/~rjones/virt-df/ From markmc at redhat.com Tue Jul 28 18:47:43 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Tue, 28 Jul 2009 19:47:43 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <20090728181601.GA18139@amd.home.annexia.org> References: <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <20090728181522.GA17223@amd.home.annexia.org> <20090728181601.GA18139@amd.home.annexia.org> Message-ID: <1248806863.3089.77.camel@blaa> On Tue, 2009-07-28 at 19:16 +0100, Richard W.M. Jones wrote: > On Tue, Jul 28, 2009 at 07:15:22PM +0100, Richard W.M. Jones wrote: > > It seems like a qemu-TCG-on-Xen problem (yet again). > > I wasn't just complaining about this - I'm going to try to > track down the emulation bug when I have some time. Yep, understood. I think TCG regressions are to be expected, really - very few people are testing TCG with qemu-kvm.git, I reckon Thanks, Mark. From crobinso at redhat.com Wed Jul 29 02:54:24 2009 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 28 Jul 2009 22:54:24 -0400 Subject: [fedora-virt] ANNOUNCE: New release virt-manager 0.8.0 Message-ID: <4A6FB9E0.2040709@redhat.com> I'm happy to announce a new virt-manager release, version 0.8.0. The release can be downloaded from: http://virt-manager.org/download.html The direct download link is: http://virt-manager.org/download/sources/virt-manager/virt-manager-0.8.0.tar.gz This release includes: - New 'Clone VM' Wizard - Improved UI, including an overhaul of the main 'manager' view - System tray icon for easy VM access (start, stop, view console/details) - Wizard for adding serial, parallel, and video devices to existing VMs. - CPU pinning support (Michal Novotny) - Ability to view and change VM security (sVirt) settings (Dan Walsh) - Many bug fixes and improvements Thanks to everyone who has contributed to this release through testing, bug reporting, submitting patches, and otherwise sending in feedback! Thanks, Cole From crobinso at redhat.com Wed Jul 29 02:54:37 2009 From: crobinso at redhat.com (Cole Robinson) Date: Tue, 28 Jul 2009 22:54:37 -0400 Subject: [fedora-virt] ANNOUNCE: New release virtinst 0.500.0 Message-ID: <4A6FB9ED.6030602@redhat.com> I'm happy to announce a new virtinst release, version 0.500.0. The release can be downloaded from: http://virt-manager.org/download.html The direct download link is: http://virt-manager.org/download/sources/virtinst/virtinst-0.500.0.tar.gz This release includes: - New virt-install device options --serial, --parallel, and --video - Allow various auth types for libvirt connections (PolicyKit, SASL, ...) - New virt-clone option --auto-clone: generates all needed input. - Option to specify network device model via virt-install --network (Guido Gunther) - New virt-install option --virt-type for specifying hypervisor type (kvm, qemu). --accelerate is now the default behavior: To provision a plain qemu VM on a KVM enabled host, use '--virt-type qemu' - OVF input support for virt-convert - Many bug fixes and improvements Thanks to everyone who has contributed to this release through testing, bug reporting, submitting patches, and otherwise sending in feedback! Thanks, Cole From markmc at redhat.com Wed Jul 29 07:19:38 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 08:19:38 +0100 Subject: [fedora-virt] Can't use network in guests In-Reply-To: References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> <1248790415.3089.65.camel@blaa> Message-ID: <1248851978.3021.5.camel@blaa> On Tue, 2009-07-28 at 16:35 +0200, Gianluca Sforna wrote: > On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: > >> > >> > >> > >> > > > > Try deleting this line > > I tried removing the line with virsh edit, but restarting the VM with > virsh start leads to the same error. I double checked and the line > appeared again, I've no idea how it got there again... Please file a bug on this - dumpxml/edit should never show dev='vnet%d' Thanks, Mark. From markmc at redhat.com Wed Jul 29 09:27:29 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 10:27:29 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248776732.3089.45.camel@blaa> References: <1242754355.9151.8.camel@blaa> <1242913633.28844.46.camel@blaa> <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> Message-ID: <1248859649.3021.28.camel@blaa> Hi, A bunch more fixes for the libvirt-0.7.0 snapshot is available in rawhide and the virt-preview repository: (Note: netcf, capng and qemu-user is still disabled in the virt-preview builds) * Wed Jul 29 2009 Mark McLoughlin - 0.7.0-0.5.gitf055724 - Move ldconfig call to libvirt-client %post/%postun - Fix rpmlint warning about libvirt-client summary - Fix disabling polkit and netcf on older fedoras * Wed Jul 29 2009 Mark McLoughlin - 0.7.0-0.4.gitf055724 - Drop explicit libselinux requires, it is autorequired - Drop cleanup of python/tests, apparently not needed - Cherry-pick upstream patch to convert NEWS to UTF-8, drop iconv - Drop python BR; python-devel requires it * Tue Jul 28 2009 Mark McLoughlin - 0.7.0-0.3.gitf055724 - Enable netcf support - Pass --with-qemu-user=qemu etc. to configure - Move various requires to the libvirt-client sub-package - Sync some trivial cleanups from upstream spec file - Remove explicit libxml2 requires, again - Build with --without-capng if capng support is disabled - Remove explicit dir creating in makeinstall, replaced by attr in files - Set perms on /var/{run,lib,cache}/libvirt/qemu Cheers, Mark. From ondrejj at salstar.sk Wed Jul 29 09:36:37 2009 From: ondrejj at salstar.sk (=?utf-8?B?SsOhbiBPTkRSRUogKFNBTCk=?=) Date: Wed, 29 Jul 2009 11:36:37 +0200 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248859649.3021.28.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> Message-ID: <20090729093637.GC10723@salstar.sk> Hello, are there plans to ass virt-manager-0.8.0 and new virt-install to virt-preview? F12 packages are working for me, I just prefer availability of my packages on any enabled repo. SAL On Wed, Jul 29, 2009 at 10:27:29AM +0100, Mark McLoughlin wrote: > Hi, > > A bunch more fixes for the libvirt-0.7.0 snapshot is available in > rawhide and the virt-preview repository: > > (Note: netcf, capng and qemu-user is still disabled in the virt-preview > builds) > > * Wed Jul 29 2009 Mark McLoughlin - 0.7.0-0.5.gitf055724 > - Move ldconfig call to libvirt-client %post/%postun > - Fix rpmlint warning about libvirt-client summary > - Fix disabling polkit and netcf on older fedoras > > * Wed Jul 29 2009 Mark McLoughlin - 0.7.0-0.4.gitf055724 > - Drop explicit libselinux requires, it is autorequired > - Drop cleanup of python/tests, apparently not needed > - Cherry-pick upstream patch to convert NEWS to UTF-8, drop iconv > - Drop python BR; python-devel requires it > > * Tue Jul 28 2009 Mark McLoughlin - 0.7.0-0.3.gitf055724 > - Enable netcf support > - Pass --with-qemu-user=qemu etc. to configure > - Move various requires to the libvirt-client sub-package > - Sync some trivial cleanups from upstream spec file > - Remove explicit libxml2 requires, again > - Build with --without-capng if capng support is disabled > - Remove explicit dir creating in makeinstall, replaced by attr in files > - Set perms on /var/{run,lib,cache}/libvirt/qemu > > Cheers, > Mark. > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt From giallu at gmail.com Wed Jul 29 09:42:38 2009 From: giallu at gmail.com (Gianluca Sforna) Date: Wed, 29 Jul 2009 11:42:38 +0200 Subject: [fedora-virt] Can't use network in guests In-Reply-To: <1248851978.3021.5.camel@blaa> References: <1248776948.3089.48.camel@blaa> <1248780044.3089.59.camel@blaa> <4A6EF164.4050404@redhat.com> <1248790415.3089.65.camel@blaa> <1248851978.3021.5.camel@blaa> Message-ID: On Wed, Jul 29, 2009 at 9:19 AM, Mark McLoughlin wrote: > On Tue, 2009-07-28 at 16:35 +0200, Gianluca Sforna wrote: >> On Tue, Jul 28, 2009 at 4:13 PM, Mark McLoughlin wrote: >> >> ? ? >> >> ? ? ? >> >> ? ? ? >> >> ? ? ? >> > >> > Try deleting this line >> >> I tried removing the line with virsh edit, but restarting the VM with >> virsh start leads to the same error. I double checked and the line >> appeared again, I've no idea how it got there again... > > Please file a bug on this - dumpxml/edit should never show dev='vnet%d' https://bugzilla.redhat.com/show_bug.cgi?id=514472 -- Gianluca Sforna http://morefedora.blogspot.com http://www.linkedin.com/in/gianlucasforna From ondrejj at salstar.sk Wed Jul 29 10:21:38 2009 From: ondrejj at salstar.sk (=?utf-8?B?SsOhbiBPTkRSRUogKFNBTCk=?=) Date: Wed, 29 Jul 2009 12:21:38 +0200 Subject: [fedora-virt] ANNOUNCE: New release virt-manager 0.8.0 In-Reply-To: <4A6FB9E0.2040709@redhat.com> References: <4A6FB9E0.2040709@redhat.com> Message-ID: <20090729102138.GD10723@salstar.sk> Hello, new virt-manager looks nice and is working well for me, but I have some comments: - gray color for "Not Connected" hosts looks a bit cold. I have aprox 10 hosts configured and whole screen is cold. May be it will be nicer to add an image, like for running/stopped guest and also ability to connect/disconned by clicking on this image. - host CPU usage is missing. In older virt-manager there was also CPU usage graphs on main screen for host, not only for guests - guest CPU usage box is too high, if I have multiple hosts and guests, they need to be on multiple pages due to hight of this box. - when tryed to force poweroff guest with older libvirt, guest was stopped, but python exception was raised. After update of libvirt from virt-preview repository this message disappeared. - only one graph can be displayed. I have to choose, if I need network, disk or CPU graph and only one can be displayed. With older version there was multiple graphs available. - in virt-manager icon on panel, can you please sort hosts in same order like in main window and may be hide "not connected" hosts (virt-manager icon can't do anything with non-connected hosts). And one thing, which can make me happy. When I am trying virtual machines, I often reinstall existing one. Then I need to boot from network and after installation again from disk. I can't test new gPXE until it will work with my F11 kernel, may be it's better with this, but with currently functional bootrom I can't boot from disk if network boot is enabled and vice versa. If my guest is set to boot from disk (after previous installation) and I need to reinstall it, I have to do these steps: - click details panel (i) - click "Boot Options" - click on "Boot Device" menu - select "Network (PXE)" and confirm (click) - click "Apply" - click back to guest console - click start (play button) If my guest was running and I have to force it off, these additional steps are required: - click on "v" button right of poweroff button - click force off - click "Yes" Can this process be a bit simplified, 7-10 steps are too many. When testing development/rawhide systems, I have to repeat these steps multiple times. Do we really need this "Apply" button. I looked a bit to virt-manager sources and may be apply code can be called after boot device was changed. These are only suggestions for improvements. You can ignore them, if you consider it non useful. :-) Btw, virt-manager-0.8 in virt-preview can be useful. :-) Thank you for a nice software. SAL On Tue, Jul 28, 2009 at 10:54:24PM -0400, Cole Robinson wrote: > I'm happy to announce a new virt-manager release, version 0.8.0. The > release can be downloaded from: > > http://virt-manager.org/download.html > > The direct download link is: > > http://virt-manager.org/download/sources/virt-manager/virt-manager-0.8.0.tar.gz > > This release includes: > > - New 'Clone VM' Wizard > - Improved UI, including an overhaul of the main 'manager' view > - System tray icon for easy VM access (start, stop, view console/details) > - Wizard for adding serial, parallel, and video devices to existing VMs. > - CPU pinning support (Michal Novotny) > - Ability to view and change VM security (sVirt) settings (Dan Walsh) > - Many bug fixes and improvements > > Thanks to everyone who has contributed to this release through testing, > bug reporting, submitting patches, and otherwise sending in feedback! > > Thanks, > Cole From ondrejj at salstar.sk Wed Jul 29 11:03:06 2009 From: ondrejj at salstar.sk (=?utf-8?B?IkrDoW4gT05EUkVKIChTQUwpIg==?=) Date: Wed, 29 Jul 2009 13:03:06 +0200 Subject: [libvirt] Re: [fedora-virt] ANNOUNCE: New release virt-manager 0.8.0 In-Reply-To: <4A7024D1.6090306@compton.nu> References: <4A6FB9E0.2040709@redhat.com> <20090729102138.GD10723@salstar.sk> <4A7024D1.6090306@compton.nu> Message-ID: <20090729110306.GE10723@salstar.sk> On Wed, Jul 29, 2009 at 11:30:41AM +0100, Tom Hughes wrote: > On 29/07/09 11:21, J?n ONDREJ (SAL) wrote: > >> And one thing, which can make me happy. When I am trying virtual machines, I >> often reinstall existing one. Then I need to boot from network and after >> installation again from disk. I can't test new gPXE until it will work with >> my F11 kernel, may be it's better with this, but with currently functional >> bootrom I can't boot from disk if network boot is enabled and vice versa. >> If my guest is set to boot from disk (after previous installation) >> and I need to reinstall it, I have to do these steps: >> >> - click details panel (i) >> - click "Boot Options" >> - click on "Boot Device" menu >> - select "Network (PXE)" and confirm (click) >> - click "Apply" >> - click back to guest console >> - click start (play button) > > That's not a virt-manager issue, it's a qemu issue I assume. > > It works for me though - if I have network boot selected that I can > bring up the boot menu with F12 and select the hard disk instead? > > What I suspect you may be referring to is the fact that if you don't > have network boot set as the default then the F12 boot menu doesn't > include the network option - so you can't be set to boot from the hard > disk by default and then choose to boot from network instead using the > boot menu. > > I too find that rather annoying, but as I say it is (I believe) a qemu > issue rather than a libvirt issue. I agree. On a real PC, I can press "F12" key to boot from PXE or to select different like preset boot device. But virt-manager can simplify change to/from PXE, for example: - change input box for boot device to radius buttons - remove "Apply" button and apply automatically (at least if possible) SAL From markmc at redhat.com Wed Jul 29 11:53:58 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 12:53:58 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <20090729093637.GC10723@salstar.sk> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> Message-ID: <1248868438.3021.31.camel@blaa> On Wed, 2009-07-29 at 11:36 +0200, J?n ONDREJ (SAL) wrote: > Hello, > > are there plans to ass virt-manager-0.8.0 and new virt-install to > virt-preview? F12 packages are working for me, I just prefer > availability of my packages on any enabled repo. Good point - I'll build them. Thanks, Mark. From markmc at redhat.com Wed Jul 29 13:20:40 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 14:20:40 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248868438.3021.31.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> Message-ID: <1248873640.3021.34.camel@blaa> Hey, The new versions of python-virtinst and virt-manager are now available in virt-preview: === python-virtinst === * Tue Jul 28 2009 Cole Robinson - 0.500.0-1.fc12 - Update to version 0.500.0 - New virt-install device options --serial, --parallel, and --video - Allow various auth types for libvirt connections (PolicyKit, SASL, ...) - New virt-clone option --auto-clone: generates all needed input. - Specify network device model via virt-install --network (Guido Gunther) === virt-manager === * Tue Jul 28 2009 Cole Robinson - 0.8.0-1.fc12 - Update to release 0.8.0 - New 'Clone VM' Wizard - Improved UI, including an overhaul of the main 'manager' view - System tray icon for easy VM access (start, stop, view console/details) - Wizard for adding serial, parallel, and video devices to existing VMs. Cheers, Mark. From markmc at redhat.com Wed Jul 29 14:57:42 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 15:57:42 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248873640.3021.34.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> <1248873640.3021.34.camel@blaa> Message-ID: <1248879462.3021.39.camel@blaa> Goodness, it's all action today - a virt-viewer update now: * Wed Jul 29 2009 Daniel P. Berrange - 0.2.0-1.fc12 - Update to 0.2.0 release Cheers, Mark. From markmc at redhat.com Wed Jul 29 15:45:36 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Wed, 29 Jul 2009 16:45:36 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248879462.3021.39.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> <1248873640.3021.34.camel@blaa> <1248879462.3021.39.camel@blaa> Message-ID: <1248882336.3021.40.camel@blaa> and now another libvirt 0.7.0 pre-release snapshot: * Wed Jul 29 2009 Daniel Veillard - 0.7.0-0.6.gite195b43 - another prerelease with qemu, uml and remote patches - drop the news patch as it's now UTF8 upstream Cheers, Mark. From markmc at redhat.com Thu Jul 30 17:23:43 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Thu, 30 Jul 2009 18:23:43 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248882336.3021.40.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> <1248873640.3021.34.camel@blaa> <1248879462.3021.39.camel@blaa> <1248882336.3021.40.camel@blaa> Message-ID: <1248974623.3275.4.camel@blaa> More updates available in http://markmc.fedorapeople.org/virt-preview == qemu == * Thu Jul 30 2009 Mark McLoughlin - 2:0.10.91-0.1.rc1.rc0 - Update to qemu-kvm-0.11.0-rc1-rc0 - This is a pre-release of the official -rc1 - A vista installer regression is blocking the official -rc1 release - Drop qemu-prefer-sysfs-for-usb-host-devices.patch - Drop qemu-fix-build-for-esd-audio.patch - Drop qemu-slirp-Fix-guestfwd-for-incoming-data.patch - Add patch to ensure extboot.bin is installed == libvirt == * Thu Jul 30 2009 Mark McLoughlin - 0.7.0-0.8.gite195b43 - Add patch from upstream to fix qemu pidfile perms problem * Thu Jul 30 2009 Daniel P. Berrange - 0.7.0-0.7.gite195b43 - Create qemu/kvm user & group to fix upgrades Cheers, Mark. From thatch45 at gmail.com Fri Jul 31 15:23:02 2009 From: thatch45 at gmail.com (Thomas S Hatch) Date: Fri, 31 Jul 2009 09:23:02 -0600 Subject: [fedora-virt] Supermin question Message-ID: <6172c17e0907310823v60edaf0fu6567219f2cefe4cf@mail.gmail.com> I imagine I am missing something obvious, but I can't figure out how to start a supermin appliance. I ran the helper script and generated my initrd and symbolic link to my kernel, but I can't figure out how to use it beyond that, how to actually boot it. Thanks! -Tom Hatch -------------- next part -------------- An HTML attachment was scrubbed... URL: From mbooth at redhat.com Fri Jul 31 15:45:32 2009 From: mbooth at redhat.com (Matthew Booth) Date: Fri, 31 Jul 2009 16:45:32 +0100 Subject: [fedora-virt] Supermin question In-Reply-To: <6172c17e0907310823v60edaf0fu6567219f2cefe4cf@mail.gmail.com> References: <6172c17e0907310823v60edaf0fu6567219f2cefe4cf@mail.gmail.com> Message-ID: <4A73119C.2030104@redhat.com> On 31/07/09 16:23, Thomas S Hatch wrote: > I imagine I am missing something obvious, but I can't figure out how to > start a supermin appliance. I ran the helper script and generated my > initrd and symbolic link to my kernel, but I can't figure out how to use > it beyond that, how to actually boot it. > Thanks! If you configured libguestfs with supermin (./configure --enable-supermin), it will automatically create the supermin appliance every time you invoke libguestfs. You don't ever have to create the appliance manually. Matt -- Matthew Booth, RHCA, RHCSS Red Hat Engineering, Virtualisation Team M: +44 (0)7977 267231 GPG ID: D33C3490 GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490 From markmc at redhat.com Fri Jul 31 16:17:02 2009 From: markmc at redhat.com (Mark McLoughlin) Date: Fri, 31 Jul 2009 17:17:02 +0100 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1248974623.3275.4.camel@blaa> References: <1244034684.5001.134.camel@blaa> <1244046483.5001.180.camel@blaa> <1244197459.27876.0.camel@blaa> <1246303956.11688.148.camel@blaa> <1246628572.13604.2.camel@blaa> <1246636154.13604.8.camel@blaa> <1247763853.3038.105.camel@blaa> <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> <1248873640.3021.34.camel@blaa> <1248879462.3021.39.camel@blaa> <1248882336.3021.40.camel@blaa> <1248974623.3275.4.camel@blaa> Message-ID: <1249057022.3320.35.camel@blaa> More updates available in http://markmc.fedorapeople.org/virt-preview == qemu == * Fri Jul 31 2009 Mark McLoughlin - 2:0.10.91-0.2.rc1.rc0 - Add KSM support - Require bochs-bios >= 2.3.8-0.8 for latest kvm bios updates == libvirt == * Fri Jul 31 2009 Mark McLoughlin - 0.7.0-0.9.gite195b43 - Set perms on /var/lib/libvirt/images to 0711 == bochs-bios == * Fri Jul 31 2009 Glauber Costa - 2:0.10.50-14.kvm88 - replace kvm-bios with a more modern version, and refresh instructions on how to get it. Cheers, Mark. From ondrejj at salstar.sk Fri Jul 31 16:57:40 2009 From: ondrejj at salstar.sk (=?utf-8?B?SsOhbiBPTkRSRUogKFNBTCk=?=) Date: Fri, 31 Jul 2009 18:57:40 +0200 Subject: [fedora-virt] ANNOUNCE: Rawhide virt repo for F11 users In-Reply-To: <1249057022.3320.35.camel@blaa> References: <1248769817.3089.20.camel@blaa> <1248776732.3089.45.camel@blaa> <1248859649.3021.28.camel@blaa> <20090729093637.GC10723@salstar.sk> <1248868438.3021.31.camel@blaa> <1248873640.3021.34.camel@blaa> <1248879462.3021.39.camel@blaa> <1248882336.3021.40.camel@blaa> <1248974623.3275.4.camel@blaa> <1249057022.3320.35.camel@blaa> Message-ID: <20090731165740.GC2701@salstar.sk> groupadd: GID 107 is not singular useradd: unknown group qemu Non-fatal POSTIN scriptlet failure in rpm package 2:qemu-common-0.10.91-0.2.rc1.rc0.fc11.i586 varovanie: %post(qemu-common-2:0.10.91-0.2.rc1.rc0.fc11.i586) scriptlet failed, exit status 6 Messages have been manually translated from slovak (my language) to english. May be they are not correct. OpenVPN is using gid 107 on my system. virtio booting is still not working. :( SAL On Fri, Jul 31, 2009 at 05:17:02PM +0100, Mark McLoughlin wrote: > More updates available in http://markmc.fedorapeople.org/virt-preview > > == qemu == > > * Fri Jul 31 2009 Mark McLoughlin - 2:0.10.91-0.2.rc1.rc0 > - Add KSM support > - Require bochs-bios >= 2.3.8-0.8 for latest kvm bios updates > > == libvirt == > > * Fri Jul 31 2009 Mark McLoughlin - 0.7.0-0.9.gite195b43 > - Set perms on /var/lib/libvirt/images to 0711 > > == bochs-bios == > > * Fri Jul 31 2009 Glauber Costa - 2:0.10.50-14.kvm88 > - replace kvm-bios with a more modern version, and refresh instructions on how to get it. > > Cheers, > Mark. > > > _______________________________________________ > Fedora-virt mailing list > Fedora-virt at redhat.com > https://www.redhat.com/mailman/listinfo/fedora-virt From tom at compton.nu Wed Jul 29 10:30:41 2009 From: tom at compton.nu (Tom Hughes) Date: Wed, 29 Jul 2009 11:30:41 +0100 Subject: [libvirt] Re: [fedora-virt] ANNOUNCE: New release virt-manager 0.8.0 In-Reply-To: <20090729102138.GD10723@salstar.sk> References: <4A6FB9E0.2040709@redhat.com> <20090729102138.GD10723@salstar.sk> Message-ID: <4A7024D1.6090306@compton.nu> On 29/07/09 11:21, J?n ONDREJ (SAL) wrote: > And one thing, which can make me happy. When I am trying virtual machines, I > often reinstall existing one. Then I need to boot from network and after > installation again from disk. I can't test new gPXE until it will work with > my F11 kernel, may be it's better with this, but with currently functional > bootrom I can't boot from disk if network boot is enabled and vice versa. > If my guest is set to boot from disk (after previous installation) > and I need to reinstall it, I have to do these steps: > > - click details panel (i) > - click "Boot Options" > - click on "Boot Device" menu > - select "Network (PXE)" and confirm (click) > - click "Apply" > - click back to guest console > - click start (play button) That's not a virt-manager issue, it's a qemu issue I assume. It works for me though - if I have network boot selected that I can bring up the boot menu with F12 and select the hard disk instead? What I suspect you may be referring to is the fact that if you don't have network boot set as the default then the F12 boot menu doesn't include the network option - so you can't be set to boot from the hard disk by default and then choose to boot from network instead using the boot menu. I too find that rather annoying, but as I say it is (I believe) a qemu issue rather than a libvirt issue. Tom -- Tom Hughes (tom at compton.nu) http://www.compton.nu/