>From e80f093e91e6769da072fe74a94e71719ce47931 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Thu, 17 Sep 2009 14:55:50 +0100 Subject: [PATCH 3/3] Enable alternate vmchannel method (non-upstream virtio-console). This patch enables an alternate vmchannel method, Amit Shah's non-upstream multiport virtio-console: http://git.kernel.org/?p=linux/kernel/git/amit/vs-kernel.git;a=summary http://git.kernel.org/?p=linux/kernel/git/amit/vs-qemu-kvm.git;a=summary On the library side, we try to detect if qemu offers this feature, and if so we use it in preference to guestfwd. On the daemon side, we detect if this method is being used (/dev/vcon4 device will appear), and use that. The only change required is in the code which enables/detects this feature. Apart from that, the socket and protocol all works exactly the same way. NOTE: multiport virtio-console doesn't work if there is any load on the host. Random read() calls return 0 (EOF) incorrectly. For this and other reasons, this patch is *not* to be applied to libguestfs. --- daemon/guestfsd.c | 30 +++++++++++++++++++++++++++--- src/guestfs.c | 23 +++++++++++++++++------ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index bfd8139..ca85db7 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -45,6 +45,7 @@ static void usage (void); /* Also in guestfs.c */ #define GUESTFWD_PORT "6666" #define GUESTFWD_ADDR "10.0.2.4" +#define VIRTIOCONSOLE_PORT "4" int verbose = 0; @@ -155,7 +156,16 @@ main (int argc, char *argv[]) /* We document that umask defaults to 022 (it should be this anyway). */ umask (022); - /* Resolve the hostname. */ + /* Look for each possible vmchannel implementation in turn + * until one succeeds. + */ + + /* Look for Amit Shah's multiport virtio-console device. */ + sock = open ("/dev/vcon" VIRTIOCONSOLE_PORT, O_RDWR); + if (sock >= 0) + goto connected; + + /* Look for the QEmu guestfwd network port. */ memset (&hints, 0, sizeof hints); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; @@ -181,12 +191,26 @@ main (int argc, char *argv[]) } freeaddrinfo (res); + /* All vmchannel methods failed. */ if (sock == -1) { - fprintf (stderr, "connection to %s:%s failed\n", - GUESTFWD_ADDR, GUESTFWD_PORT); + fprintf (stderr, + "\n" + "Failed to connect to any vmchannel implementation.\n" + "\n" + "This is a fatal error and the appliance will now exit.\n" + "\n" + "Usually this error is caused by either QEMU or the appliance\n" + "kernel not supporting the vmchannel method that the\n" + "libguestfs library chose to use. Please run\n" + "'libguestfs-test-tool' and provide the complete, unedited\n" + "output to the libguestfs developers, either in a bug report\n" + "or on the libguestfs@redhat.com mailing list.\n" + "\n" + ); exit (1); } + connected: /* Send the magic length message which indicates that * userspace is up inside the guest. */ diff --git a/src/guestfs.c b/src/guestfs.c index 069de45..7a09131 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -87,6 +87,7 @@ static void close_handles (void); /* Also in guestfsd.c */ #define GUESTFWD_PORT 6666 //#define GUESTFWD_ADDR "10.0.2.4" +#define VIRTIOCONSOLE_PORT 4 /* GuestFS handle and connection. */ enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE }; @@ -1025,6 +1026,14 @@ guestfs__launch (guestfs_h *g) add_cmdline (g, "-serial"); add_cmdline (g, "stdio"); + /* Choose a vmchannel method by detecting what qemu supports. */ + if (qemu_supports (g, "virtio console (multiport)")) { + snprintf (vmchannel, sizeof vmchannel, + "unix:%s,server,nowait,port=%d", + unixsock, VIRTIOCONSOLE_PORT); + add_cmdline (g, "-virtioconsole"); + add_cmdline (g, vmchannel); + } else #if 0 /* Doesn't work. See: * http://lists.gnu.org/archive/html/qemu-devel/2009-07/threads.html @@ -1035,13 +1044,17 @@ guestfs__launch (guestfs_h *g) * http://git.savannah.gnu.org/cgit/qemu.git/commit/?id=c92ef6a22d3c71538fcc48fb61ad353f7ba03b62 */ snprintf (vmchannel, sizeof vmchannel, - "user,vlan=0,net=10.0.2.0/8,guestfwd=tcp:%s:%d-unix:%s,server,nowait", + "user,vlan=0,net=10.0.2.0/8," + "guestfwd=tcp:%s:%d-unix:%s,server,nowait", GUESTFWD_ADDR, GUESTFWD_PORT, unixsock); add_cmdline (g, "-net"); add_cmdline (g, vmchannel); - } else { + add_cmdline (g, "-net"); + add_cmdline (g, "nic,model=" NET_IF ",vlan=0"); + } else #endif + { /* Not guestfwd. HOPEFULLY this qemu uses the older -net channel * syntax, or if not then we'll get a quick failure. */ @@ -1053,11 +1066,9 @@ guestfs__launch (guestfs_h *g) add_cmdline (g, vmchannel); add_cmdline (g, "-net"); add_cmdline (g, "user,vlan=0,net=10.0.2.0/8"); -#if 0 + add_cmdline (g, "-net"); + add_cmdline (g, "nic,model=" NET_IF ",vlan=0"); } -#endif - add_cmdline (g, "-net"); - add_cmdline (g, "nic,model=" NET_IF ",vlan=0"); /* These options recommended by KVM developers to improve reliability. */ if (qemu_supports (g, "-no-hpet")) -- 1.6.2.5