Richard W.M. Jones
2016-May-18 15:11 UTC
[Libguestfs] [PATCH v2 0/2] Use -bios bios-fast.bin where supported.
This commit uses -bios bios-fast.bin if available, which basically stops SeaBIOS from trying to do PCI probing during boot, which is a waste of time when using the -kernel option. v1 -> v2: - Rebase on top of Pino's work. This still has 3 dependencies: - The qemu memoization work (v2). - Support for '-L ?' in qemu: https://lists.gnu.org/archive/html/qemu-devel/2016-05/threads.html#02596 - Support for bios-fast.bin in qemu: https://lists.gnu.org/archive/html/qemu-devel/2016-05/threads.html#02408 Rich.
Richard W.M. Jones
2016-May-18 15:11 UTC
[Libguestfs] [PATCH v2 1/2] qemu: Add a function to test if -bios feature is supported.
This has to read the data dirs from qemu using the new 'qemu -L ?' flag added in qemu 2.7. --- src/guestfs-internal.h | 1 + src/qemu.c | 89 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 6004890..ebc3e59 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -919,6 +919,7 @@ struct qemu_data; extern struct qemu_data *guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version); extern int guestfs_int_qemu_supports (guestfs_h *g, const struct qemu_data *, const char *option); extern int guestfs_int_qemu_supports_device (guestfs_h *g, const struct qemu_data *, const char *device_name); +extern int guestfs_int_qemu_supports_bios (guestfs_h *g, const struct qemu_data *, const char *bios_name); extern int guestfs_int_qemu_supports_virtio_scsi (guestfs_h *g, struct qemu_data *, const struct version *qemu_version); extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src); extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, const struct version *qemu_version); diff --git a/src/qemu.c b/src/qemu.c index 11bf5cf..c59aed9 100644 --- a/src/qemu.c +++ b/src/qemu.c @@ -48,11 +48,12 @@ COMPILE_REGEXP (re_major_minor, "(\\d+)\\.(\\d+)", 0) struct qemu_data { - char *qemu_help; /* Output of qemu -help. */ - char *qemu_devices; /* Output of qemu -device ? */ + char *qemu_help; /* Output of qemu -help. */ + char *qemu_devices; /* Output of qemu -device ? */ + char *qemu_datadirs; /* Output of qemu -L ? (NULL if not supported) */ - int virtio_scsi; /* See function - guestfs_int_qemu_supports_virtio_scsi */ + int virtio_scsi; /* See function + guestfs_int_qemu_supports_virtio_scsi */ }; static int test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version); @@ -68,8 +69,9 @@ static void read_all (guestfs_h *g, void *retv, const char *buf, size_t len); /** * Test qemu binary (or wrapper) runs, and do C<qemu -help> so we know - * the version of qemu what options this qemu supports, and - * C<qemu -device ?> so we know what devices are available. + * the version of qemu what options this qemu supports, + * C<qemu -device ?> so we know what devices are available, + * and C<qemu -L ?> to list data directories. * * The version number of qemu (from the C<-help> output) is saved in * C<&qemu_version>. @@ -83,7 +85,8 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version) struct qemu_data *data; struct stat statbuf; CLEANUP_FREE char *cachedir = NULL, *qemu_stat_filename = NULL, - *qemu_help_filename = NULL, *qemu_devices_filename = NULL; + *qemu_help_filename = NULL, *qemu_devices_filename = NULL, + *qemu_datadirs_filename = NULL; FILE *fp; int generation; uint64_t prev_size, prev_mtime; @@ -100,6 +103,7 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version) qemu_stat_filename = safe_asprintf (g, "%s/qemu.stat", cachedir); qemu_help_filename = safe_asprintf (g, "%s/qemu.help", cachedir); qemu_devices_filename = safe_asprintf (g, "%s/qemu.devices", cachedir); + qemu_datadirs_filename = safe_asprintf (g, "%s/qemu.datadirs", cachedir); /* Did we previously test the same version of qemu? */ debug (g, "checking for previously cached test results of %s, in %s", @@ -122,7 +126,8 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version) * and qemu -devices ? output. */ if (access (qemu_help_filename, R_OK) == -1 || - access (qemu_devices_filename, R_OK) == -1) + access (qemu_devices_filename, R_OK) == -1 || + access (qemu_datadirs_filename, R_OK) == -1) goto do_test; debug (g, "loading previously cached test results"); @@ -143,6 +148,12 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version) return NULL; } + if (guestfs_int_read_whole_file (g, qemu_datadirs_filename, + &data->qemu_datadirs, NULL) == -1) { + guestfs_int_free_qemu_data (data); + return NULL; + } + return data; } @@ -183,6 +194,19 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version) if (fclose (fp) == -1) goto devices_error; + fp = fopen (qemu_datadirs_filename, "w"); + if (fp == NULL) { + datadirs_error: + perrorf (g, "%s", qemu_datadirs_filename); + if (fp != NULL) fclose (fp); + guestfs_int_free_qemu_data (data); + return NULL; + } + if (fprintf (fp, "%s", data->qemu_datadirs) == -1) + goto datadirs_error; + if (fclose (fp) == -1) + goto datadirs_error; + /* Write the qemu.stat file last so that its presence indicates that * the qemu.help and qemu.devices files ought to exist. */ @@ -214,6 +238,7 @@ test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version) { CLEANUP_CMD_CLOSE struct command *cmd1 = guestfs_int_new_command (g); CLEANUP_CMD_CLOSE struct command *cmd2 = guestfs_int_new_command (g); + CLEANUP_CMD_CLOSE struct command *cmd3 = guestfs_int_new_command (g); int r; guestfs_int_cmd_add_arg (cmd1, g->hv); @@ -247,6 +272,28 @@ test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version) if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) goto error; + /* qemu -L ? only supported in qemu >= 2.7 */ + if (guestfs_int_version_ge (qemu_version, 2, 7, 0)) { + guestfs_int_cmd_add_arg (cmd3, g->hv); + guestfs_int_cmd_add_arg (cmd3, "-display"); + guestfs_int_cmd_add_arg (cmd3, "none"); + guestfs_int_cmd_add_arg (cmd3, "-machine"); + guestfs_int_cmd_add_arg (cmd3, +#ifdef MACHINE_TYPE + MACHINE_TYPE "," +#endif + "accel=kvm:tcg"); + guestfs_int_cmd_add_arg (cmd3, "-L"); + guestfs_int_cmd_add_arg (cmd3, "?"); + guestfs_int_cmd_set_stdout_callback (cmd3, read_all, &data->qemu_datadirs, + CMD_STDOUT_FLAG_WHOLE_BUFFER); + r = guestfs_int_cmd_run (cmd3); + if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) + goto error; + } + else + data->qemu_datadirs = safe_strdup (g, ""); + return 0; error: @@ -321,6 +368,32 @@ guestfs_int_qemu_supports_device (guestfs_h *g, return strstr (data->qemu_devices, device_name) != NULL; } +/** + * Test if a named BIOS is supported by qemu. + */ +int +guestfs_int_qemu_supports_bios (guestfs_h *g, + const struct qemu_data *data, + const char *bios_name) +{ + CLEANUP_FREE_STRING_LIST char **datadirs; + size_t i; + + datadirs = guestfs_int_split_string ('\n', data->qemu_datadirs); + if (datadirs == NULL) + return 0; /* ignore errors, return false which is safe */ + + for (i = 0; datadirs[i] != NULL; ++i) { + CLEANUP_FREE char *path; + + path = safe_asprintf (g, "%s/%s", datadirs[i], bios_name); + if (access (path, R_OK) == 0) + return 1; + } + + return 0; +} + static int old_or_broken_virtio_scsi (const struct version *qemu_version) { -- 2.7.4
Richard W.M. Jones
2016-May-18 15:11 UTC
[Libguestfs] [PATCH v2 2/2] launch: Use -bios bios-fast.bin where supported.
This is a cut-down version of the SeaBIOS configuration optimized for booting a Linux kernel with the -kernel option on x86. It was added in qemu 2.7. Use it if available. --- src/launch-direct.c | 6 ++++++ src/launch-libvirt.c | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/launch-direct.c b/src/launch-direct.c index 30cf01a..a6f06ee 100644 --- a/src/launch-direct.c +++ b/src/launch-direct.c @@ -434,6 +434,12 @@ launch_direct (guestfs_h *g, void *datav, const char *arg) ADD_CMDLINE ("-initrd"); ADD_CMDLINE (initrd); + if (guestfs_int_qemu_supports_bios (g, data->qemu_data, "bios-fast.bin")) { + /* Use the fast variant of SeaBIOS. */ + ADD_CMDLINE ("-bios"); + ADD_CMDLINE ("bios-fast.bin"); + } + /* Add a random number generator (backend for virtio-rng). This * isn't strictly necessary but means we won't need to hang around * when needing entropy. diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index 05ab6a6..9f76afa 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -1159,6 +1159,15 @@ construct_libvirt_xml_boot (guestfs_h *g, } end_element (); } } +#if defined(__i386__) || defined(__x86_64__) + /* XXX libvirt should provide a way to detect if bios-fast.bin exists */ + else if (guestfs_int_version_ge (¶ms->data->qemu_version, 2, 7, 0)) { + /* Use the fast variant of SeaBIOS. */ + start_element ("loader") { + string ("bios-fast.bin"); + } end_element (); + } +#endif start_element ("kernel") { string (params->kernel); -- 2.7.4
Reasonably Related Threads
- [PATCH 0/2] Use -bios bios-fast.bin where supported.
- [PATCH 0/4] qemu: Use sqlite to store qemu detection data.
- [PATCH 0/4] lib: qemu: Add test for mandatory locking.
- [PATCH v3 0/6] launch: direct: Disable qemu locking when opening drives readonly.
- [PATCH v2 0/5] launch: direct: Disable qemu locking when opening drives readonly (RHBZ#1417306)