#include <string.h>
#include <fcntl.h>
#include <time.h>
+#include <sys/stat.h>
#include <sys/select.h>
+
#include <rpc/types.h>
#include <rpc/xdr.h>
int autosync;
const char *path;
+ const char *qemu;
char *last_error;
str = getenv ("LIBGUESTFS_PATH");
g->path = str != NULL ? str : GUESTFS_DEFAULT_PATH;
- /* XXX We should probably make QEMU configurable as well. */
+
+ str = getenv ("LIBGUESTFS_QEMU");
+ g->qemu = str != NULL ? str : QEMU;
g->main_loop = guestfs_get_default_main_loop ();
return g->path;
}
+int
+guestfs_set_qemu (guestfs_h *g, const char *qemu)
+{
+ if (qemu == NULL)
+ g->qemu = QEMU;
+ else
+ g->qemu = qemu;
+ return 0;
+}
+
+const char *
+guestfs_get_qemu (guestfs_h *g)
+{
+ return g->qemu;
+}
+
/* Add a string to the current command line. */
static void
incr_cmdline_size (guestfs_h *g)
guestfs_launch (guestfs_h *g)
{
static const char *dir_template = "/tmp/libguestfsXXXXXX";
- int r, i, len, pmore;
+ int r, i, len, pmore, memsize;
int wfd[2], rfd[2];
int tries;
const char *kernel_name = "vmlinuz." REPO "." host_cpu;
char *kernel = NULL, *initrd = NULL;
char unixsock[256];
struct sockaddr_un addr;
+ struct stat statbuf;
/* Configured? */
if (!g->cmdline) {
goto cleanup0;
}
+ /* Choose a suitable memory size (in MB). This is more art
+ * than science, but you can help by doing
+ * ./configure --enable-debug-command
+ * and then running:
+ * debug sh free
+ * debug mem ''
+ * and seeing how much free memory is left for particular
+ * configurations.
+ *
+ * It's also helpful to report both the compressed and uncompressed
+ * size of the initramfs (ls -lh initramfs*.img; du -sh initramfs).
+ *
+ * XXX KVM virtio balloon driver?
+ */
+ if (stat (initrd, &statbuf) != -1) {
+ /* Approximate size of the initramfs after it is decompressed
+ * in kernel memory. The compression factor is ~2.5-3.
+ */
+ memsize = 3 * statbuf.st_size / 1024 / 1024;
+
+ /* Approximate size used by the kernel. */
+ memsize += 10;
+
+ /* Want to give userspace some room, so: */
+ memsize += 128;
+
+#if AC_SIZEOF_LONG == 8
+ /* On 64 bit, assume some overhead. */
+ memsize += 32;
+#endif
+ } else
+ memsize = 512;
+
+
/* Make the temporary directory containing the socket. */
if (!g->tmpdir) {
g->tmpdir = safe_strdup (g, dir_template);
if (r == 0) { /* Child (qemu). */
char vmchannel[256];
char append[256];
+ char memsize_str[256];
/* Set up the full command line. Do this in the subprocess so we
* don't need to worry about cleaning up.
*/
- g->cmdline[0] = (char *) QEMU;
+ g->cmdline[0] = (char *) g->qemu;
/* Construct the -net channel parameter for qemu. */
snprintf (vmchannel, sizeof vmchannel,
VMCHANNEL_ADDR, VMCHANNEL_PORT,
g->verbose ? " guestfs_verbose=1" : "");
+ snprintf (memsize_str, sizeof memsize_str, "%d", memsize);
+
add_cmdline (g, "-m");
- add_cmdline (g, "384"); /* XXX Choose best size. */
-#if defined(__i386__) || defined(__x86_64)
+ add_cmdline (g, memsize_str);
+#if 0
add_cmdline (g, "-no-kqemu"); /* Avoids a warning. */
#endif
add_cmdline (g, "-kernel");
add_cmdline (g, "-net");
add_cmdline (g, "user,vlan=0");
add_cmdline (g, "-net");
- add_cmdline (g, "nic,vlan=0");
+ add_cmdline (g, "nic,model=rtl8139,vlan=0");
incr_cmdline_size (g);
g->cmdline[g->cmdline_size-1] = NULL;
if (g->verbose) {
- fprintf (stderr, "%s", QEMU);
+ fprintf (stderr, "%s", g->qemu);
for (i = 0; g->cmdline[i]; ++i)
fprintf (stderr, " %s", g->cmdline[i]);
fprintf (stderr, "\n");
setpgid (0, 0);
#endif
- execv (QEMU, g->cmdline); /* Run qemu. */
- perror (QEMU);
+ execv (g->qemu, g->cmdline); /* Run qemu. */
+ perror (g->qemu);
_exit (1);
}