X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Flaunch.c;h=7b3372c2bc85d43d596ff351eaf62cb15c9ace25;hb=99ec97dcdfaf242ba0683a230ba51e4a87f7458b;hp=ed8d9bdd0fb378fa5d5ce1caad2cc8d52cc1a620;hpb=a1df33eac2c0a0a4fbb256871e491e28dd11ce90;p=libguestfs.git diff --git a/src/launch.c b/src/launch.c index ed8d9bd..7b3372c 100644 --- a/src/launch.c +++ b/src/launch.c @@ -76,6 +76,7 @@ static int64_t timeval_diff (const struct timeval *x, const struct timeval *y); static void print_qemu_command_line (guestfs_h *g, char **argv); static int connect_unix_socket (guestfs_h *g, const char *sock); static int qemu_supports (guestfs_h *g, const char *option); +static char *qemu_drive_param (guestfs_h *g, const struct drive *drv); #if 0 static int qemu_supports_re (guestfs_h *g, const pcre *option_regex); @@ -186,20 +187,8 @@ guestfs__debug_drives (guestfs_h *g) ret = safe_malloc (g, sizeof (char *) * (count + 1)); - for (i = 0, drv = g->drives; drv; i++, drv = drv->next) { - size_t len = 64 + strlen (drv->path) + strlen (drv->iface); - if (drv->format) len += strlen (drv->format); - - ret[i] = safe_malloc (g, len); - - snprintf (ret[i], len, "file=%s%s%s%s%s,if=%s", - drv->path, - drv->readonly ? ",snapshot=on" : "", - drv->use_cache_off ? ",cache=off" : "", - drv->format ? ",format=" : "", - drv->format ? drv->format : "", - drv->iface); - } + for (i = 0, drv = g->drives; drv; i++, drv = drv->next) + ret[i] = qemu_drive_param (g, drv); ret[count] = NULL; @@ -244,17 +233,21 @@ guestfs__config (guestfs_h *g, * O_DIRECT. This fails on some filesystem types (notably tmpfs). * So we check if we can open the file with or without O_DIRECT, * and use cache=off (or not) accordingly. + * + * NB: This function is only called on the !readonly path. We must + * try to open with O_RDWR to test that the file is readable and + * writable here. */ static int test_cache_off (guestfs_h *g, const char *filename) { - int fd = open (filename, O_RDONLY|O_DIRECT); + int fd = open (filename, O_RDWR|O_DIRECT); if (fd >= 0) { close (fd); return 1; } - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDWR); if (fd >= 0) { close (fd); return 0; @@ -336,7 +329,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, } if (readonly) { - if (access (filename, F_OK) == -1) { + if (access (filename, R_OK) == -1) { perrorf (g, "%s", filename); free (format); free (iface); @@ -572,25 +565,16 @@ launch_appliance (guestfs_h *g) g->cmdline[0] = g->qemu; /* Add drives */ - struct drive *i = g->drives; - while (i != NULL) { + struct drive *drv = g->drives; + while (drv != NULL) { /* Construct the final -drive parameter. */ - size_t len = 64 + strlen (i->path) + strlen (i->iface); - if (i->format) len += strlen (i->format); - char buf[len]; - - snprintf (buf, len, "file=%s%s%s%s%s,if=%s", - i->path, - i->readonly ? ",snapshot=on" : "", - i->use_cache_off ? ",cache=off" : "", - i->format ? ",format=" : "", - i->format ? i->format : "", - i->iface); + char *buf = qemu_drive_param (g, drv); add_cmdline (g, "-drive"); add_cmdline (g, buf); + free (buf); - i = i->next; + drv = drv->next; } if (qemu_supports (g, "-nodefconfig")) @@ -602,7 +586,19 @@ launch_appliance (guestfs_h *g) */ 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 @@ -873,6 +869,13 @@ launch_appliance (guestfs_h *g) if (r == -1) goto cleanup1; + /* NB: We reach here just because qemu has opened the socket. It + * does not mean the daemon is up until we read the + * GUESTFS_LAUNCH_FLAG below. Failures in qemu startup can still + * happen even if we reach here, even early failures like not being + * able to open a drive. + */ + close (g->sock); /* Close the listening socket. */ g->sock = r; /* This is the accepted data socket. */ @@ -1281,6 +1284,30 @@ is_openable (guestfs_h *g, const char *path, int flags) return 1; } +static char * +qemu_drive_param (guestfs_h *g, const struct drive *drv) +{ + size_t len = 64; + char *r; + + len += strlen (drv->path); + len += strlen (drv->iface); + if (drv->format) + len += strlen (drv->format); + + r = safe_malloc (g, len); + + snprintf (r, len, "file=%s%s%s%s%s,if=%s", + drv->path, + drv->readonly ? ",snapshot=on" : "", + drv->use_cache_off ? ",cache=off" : "", + drv->format ? ",format=" : "", + drv->format ? drv->format : "", + drv->iface); + + return r; /* caller frees */ +} + /* You had to call this function after launch in versions <= 1.0.70, * but it is now a no-op. */