X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Flaunch.c;h=34d09506483202d39f0d47ff510d7aa92b69e392;hb=0cfa174589c29c3155a03df07c858f2e7a3dcaba;hp=30082d619efcee81ee1acc493d38b90c70dc28f9;hpb=dd925973467f3dd7cddbfa7e2b49a43aeb5e2b3f;p=libguestfs.git diff --git a/src/launch.c b/src/launch.c index 30082d6..34d0950 100644 --- a/src/launch.c +++ b/src/launch.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 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 @@ -71,6 +71,7 @@ #include "guestfs_protocol.h" static int launch_appliance (guestfs_h *g); +static int64_t timeval_diff (const struct timeval *x, const struct timeval *y); static int qemu_supports (guestfs_h *g, const char *option); /* Add a string to the current command line. */ @@ -382,7 +383,7 @@ launch_appliance (guestfs_h *g) { int r; int wfd[2], rfd[2]; - char unixsock[256]; + char guestfsd_sock[256]; struct sockaddr_un addr; /* At present you must add drives before starting the appliance. In @@ -411,8 +412,8 @@ launch_appliance (guestfs_h *g) /* Using virtio-serial, we need to create a local Unix domain socket * for qemu to connect to. */ - snprintf (unixsock, sizeof unixsock, "%s/sock", g->tmpdir); - unlink (unixsock); + snprintf (guestfsd_sock, sizeof guestfsd_sock, "%s/guestfsd.sock", g->tmpdir); + unlink (guestfsd_sock); g->sock = socket (AF_UNIX, SOCK_STREAM, 0); if (g->sock == -1) { @@ -426,7 +427,7 @@ launch_appliance (guestfs_h *g) } addr.sun_family = AF_UNIX; - strncpy (addr.sun_path, unixsock, UNIX_PATH_MAX); + strncpy (addr.sun_path, guestfsd_sock, UNIX_PATH_MAX); addr.sun_path[UNIX_PATH_MAX-1] = '\0'; if (bind (g->sock, &addr, sizeof addr) == -1) { @@ -472,21 +473,38 @@ launch_appliance (guestfs_h *g) if (qemu_supports (g, "-nodefconfig")) add_cmdline (g, "-nodefconfig"); - /* qemu sometimes needs this option to enable hardware - * virtualization, but some versions of 'qemu-kvm' will use KVM - * regardless (even where this option appears in the help text). - * It is rumoured that there are versions of qemu where supplying - * this option when hardware virtualization is not available will - * cause qemu to fail, so we we have to check at least that - * /dev/kvm is openable. That's not reliable, since /dev/kvm - * might be openable by qemu but not by us (think: SELinux) in - * which case the user would not get hardware virtualization, - * although at least shouldn't fail. A giant clusterfuck with the - * qemu command line, again. - */ - if (qemu_supports (g, "-enable-kvm") && - is_openable (g, "/dev/kvm", O_RDWR)) - add_cmdline (g, "-enable-kvm"); + if (qemu_supports (g, "-machine")) { + add_cmdline (g, "-machine"); +#if QEMU_MACHINE_TYPE_IS_BROKEN + /* Workaround for qemu 0.15: We have to add the '[type=]pc' + * since there is no default. This is not a permanent solution + * because this only works on PC-like hardware. Other platforms + * like ppc would need a different machine type. + * + * This bug is fixed in qemu commit 2645c6dcaf6ea2a51a, and was + * not a problem in qemu < 0.15. + */ + add_cmdline (g, "pc,accel=kvm:tcg"); +#else + add_cmdline (g, "accel=kvm:tcg"); +#endif + } else { + /* qemu sometimes needs this option to enable hardware + * virtualization, but some versions of 'qemu-kvm' will use KVM + * regardless (even where this option appears in the help text). + * It is rumoured that there are versions of qemu where supplying + * this option when hardware virtualization is not available will + * cause qemu to fail, so we we have to check at least that + * /dev/kvm is openable. That's not reliable, since /dev/kvm + * might be openable by qemu but not by us (think: SELinux) in + * which case the user would not get hardware virtualization, + * although at least shouldn't fail. A giant clusterfuck with the + * qemu command line, again. + */ + if (qemu_supports (g, "-enable-kvm") && + is_openable (g, "/dev/kvm", O_RDWR)) + add_cmdline (g, "-enable-kvm"); + } /* Newer versions of qemu (from around 2009/12) changed the * behaviour of monitors so that an implicit '-monitor stdio' is @@ -535,7 +553,7 @@ launch_appliance (guestfs_h *g) /* Set up virtio-serial for the communications channel. */ add_cmdline (g, "-chardev"); - snprintf (buf, sizeof buf, "socket,path=%s,id=channel0", unixsock); + snprintf (buf, sizeof buf, "socket,path=%s,id=channel0", guestfsd_sock); add_cmdline (g, buf); add_cmdline (g, "-device"); add_cmdline (g, "virtserialport,chardev=channel0,name=org.libguestfs.channel.0"); @@ -601,17 +619,27 @@ launch_appliance (guestfs_h *g) guestfs___print_timestamped_argv (g, (const char **)g->cmdline); if (!g->direct) { - /* Set up stdin, stdout. */ + /* Set up stdin, stdout, stderr. */ close (0); close (1); close (wfd[1]); close (rfd[0]); + /* Stdin. */ if (dup (wfd[0]) == -1) { dup_failed: perror ("dup failed"); _exit (EXIT_FAILURE); } + /* Stdout. */ + if (dup (rfd[1]) == -1) + goto dup_failed; + + /* Particularly since qemu 0.15, qemu spews all sorts of debug + * information on stderr. It is useful to both capture this and + * not confuse casual users, so send stderr to the pipe as well. + */ + close (2); if (dup (rfd[1]) == -1) goto dup_failed; @@ -654,7 +682,7 @@ launch_appliance (guestfs_h *g) pid_t parent_pid = getppid (); /* Writing to argv is hideously complicated and error prone. See: - * http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/misc/ps_status.c?rev=1.33.2.1;content-type=text%2Fplain + * http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/misc/ps_status.c;hb=HEAD */ /* Loop around waiting for one or both of the other processes to @@ -758,7 +786,7 @@ launch_appliance (guestfs_h *g) } if (g->pid > 0) kill (g->pid, 9); if (g->recoverypid > 0) kill (g->recoverypid, 9); - waitpid (g->pid, NULL, 0); + if (g->pid > 0) waitpid (g->pid, NULL, 0); if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0); g->fd[0] = -1; g->fd[1] = -1;