X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fguestfs.c;h=1d6d40bf7322edfb98c81108e384412b42ec0860;hb=97dac113f9ee7d7f2ed581db789707ff759c8cb3;hp=db291bdccd13e51e7093dffddc9790715aba03e1;hpb=3ae742c1498b8839250be295173d76b9c5731ed1;p=libguestfs.git diff --git a/src/guestfs.c b/src/guestfs.c index db291bd..1d6d40b 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009-2010 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,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,11 +60,14 @@ #include #include +#include "c-ctype.h" +#include "glthread/lock.h" +#include "ignore-value.h" + #include "guestfs.h" +#include "guestfs-internal.h" #include "guestfs-internal-actions.h" #include "guestfs_protocol.h" -#include "c-ctype.h" -#include "ignore-value.h" #ifdef HAVE_GETTEXT #include "gettext.h" @@ -147,6 +152,7 @@ struct guestfs_h int msg_next_serial; }; +gl_lock_define_initialized (static, handles_lock); static guestfs_h *handles = NULL; static int atexit_handler_set = 0; @@ -214,17 +220,15 @@ guestfs_create (void) */ g->msg_next_serial = 0x00123400; - /* Link the handles onto a global list. This is the one area - * where the library needs to be made thread-safe. (XXX) - */ - /* acquire mutex (XXX) */ + /* Link the handles onto a global list. */ + gl_lock_lock (handles_lock); g->next = handles; handles = g; if (!atexit_handler_set) { atexit (close_handles); atexit_handler_set = 1; } - /* release mutex (XXX) */ + gl_lock_unlock (handles_lock); if (g->verbose) fprintf (stderr, "new guestfs handle %p\n", g); @@ -309,7 +313,7 @@ guestfs_close (guestfs_h *g) /* Mark the handle as dead before freeing it. */ g->state = NO_HANDLE; - /* acquire mutex (XXX) */ + gl_lock_lock (handles_lock); if (handles == g) handles = g->next; else { @@ -317,7 +321,7 @@ guestfs_close (guestfs_h *g) ; gg->next = g->next; } - /* release mutex (XXX) */ + gl_lock_unlock (handles_lock); free (g->last_error); free (g->path); @@ -850,6 +854,7 @@ dir_contains_files (const char *dir, ...) return 1; } +static void print_timestamped_message (guestfs_h *g, const char *fs, ...); static int build_supermin_appliance (guestfs_h *g, const char *path, char **kernel, char **initrd); static int test_qemu (guestfs_h *g); static int qemu_supports (guestfs_h *g, const char *option); @@ -999,6 +1004,9 @@ guestfs__launch (guestfs_h *g) goto cleanup0; } + if (g->verbose) + print_timestamped_message (g, "begin testing qemu features"); + /* Get qemu help text and version. */ if (test_qemu (g) == -1) goto cleanup0; @@ -1059,6 +1067,9 @@ guestfs__launch (guestfs_h *g) } } + if (g->verbose) + print_timestamped_message (g, "finished testing qemu features"); + r = fork (); if (r == -1) { perrorf (g, "fork"); @@ -1080,15 +1091,28 @@ guestfs__launch (guestfs_h *g) */ g->cmdline[0] = g->qemu; - snprintf (buf, sizeof buf, "%d", g->memsize); - add_cmdline (g, "-m"); - add_cmdline (g, buf); + /* Newer versions of qemu (from around 2009/12) changed the + * behaviour of monitors so that an implicit '-monitor stdio' is + * assumed if we are in -nographic mode and there is no other + * -monitor option. Only a single stdio device is allowed, so + * this broke the '-serial stdio' option. There is a new flag + * called -nodefaults which gets rid of all this default crud, so + * let's use that to avoid this and any future surprises. + */ + if (qemu_supports (g, "-nodefaults")) + add_cmdline (g, "-nodefaults"); - add_cmdline (g, "-no-reboot"); /* Force exit instead of reboot on panic */ add_cmdline (g, "-nographic"); add_cmdline (g, "-serial"); add_cmdline (g, "stdio"); + snprintf (buf, sizeof buf, "%d", g->memsize); + add_cmdline (g, "-m"); + add_cmdline (g, buf); + + /* Force exit instead of reboot on panic */ + add_cmdline (g, "-no-reboot"); + /* These options recommended by KVM developers to improve reliability. */ if (qemu_supports (g, "-no-hpet")) add_cmdline (g, "-no-hpet"); @@ -1390,6 +1414,9 @@ guestfs__launch (guestfs_h *g) goto cleanup1; } + if (g->verbose) + print_timestamped_message (g, "appliance is up"); + /* 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 @@ -1468,6 +1495,9 @@ build_supermin_appliance (guestfs_h *g, const char *path, char cmd[4096]; int r, len; + if (g->verbose) + print_timestamped_message (g, "begin building supermin appliance"); + len = strlen (g->tmpdir); *kernel = safe_malloc (g, len + 8); snprintf (*kernel, len+8, "%s/kernel", g->tmpdir); @@ -1476,9 +1506,11 @@ build_supermin_appliance (guestfs_h *g, const char *path, snprintf (cmd, sizeof cmd, "PATH='%s':$PATH " - "libguestfs-supermin-helper '%s' %s %s", + "libguestfs-supermin-helper '%s' " host_cpu " " REPO " %s %s", path, path, *kernel, *initrd); + if (g->verbose) + print_timestamped_message (g, "%s", cmd); r = system (cmd); if (r == -1 || WEXITSTATUS(r) != 0) { @@ -1489,9 +1521,48 @@ build_supermin_appliance (guestfs_h *g, const char *path, return -1; } + if (g->verbose) + print_timestamped_message (g, "finished building supermin appliance"); + return 0; } +/* Compute Y - X and return the result in milliseconds. + * Approximately the same as this code: + * http://www.mpp.mpg.de/~huber/util/timevaldiff.c + */ +static int64_t +timeval_diff (const struct timeval *x, const struct timeval *y) +{ + int64_t msec; + + msec = (y->tv_sec - x->tv_sec) * 1000; + msec += (y->tv_usec - x->tv_usec) / 1000; + return msec; +} + +static void +print_timestamped_message (guestfs_h *g, const char *fs, ...) +{ + va_list args; + char *msg; + int err; + struct timeval tv, diff; + + va_start (args, fs); + err = vasprintf (&msg, fs, args); + va_end (args); + + if (err < 0) return; + + gettimeofday (&tv, NULL); + + fprintf (stderr, "[%05" PRIi64 "ms] %s\n", + timeval_diff (&g->launch_t, &tv), msg); + + free (msg); +} + static int read_all (guestfs_h *g, FILE *fp, char **ret); /* Test qemu binary (or wrapper) runs, and do 'qemu -help' and