v2v: linux: Fix Xen PV-only detection.

We want to detect if a Linux kernel is Xen PV only ("PV-only").  Such
a kernel will not boot on KVM, and if a guest has only PV-only
kernels, it will not be able to boot at all on the target.

Our previous test was wrong.  It tested whether the xennet.ko module
exists.  This module was renamed in more recent kernels (to
xen-netfront.ko), so it happened to not detect modern kernels as
PV-only, but this was by chance.

Modern kernel images can be compiled with Xen PV guest support.  The
same image can boot on baremetal, KVM, Xen PV or Xen HVM.  Testing if
the xennet (or xen-netfront) module exists is irrelevant to this.

This test, which is based on ideas from Laszlo Ersek and

  https://wiki.xen.org/wiki/Xen_Project_Software_Overview#Guest_Types

uses the kernel config test CONFIG_X86_XEN || CONFIG_X86_64_XEN to
determine PV-only kernels.

Note that these CONFIG flags were never upstream, and existed only in
Linux kernels forked by Xen ("XenLinux").  By the time Xen guest
support was added upstream, it was implemented using pvops support, so
a single image could boot on Xen and non-Xen as described above, and
these flags were no longer used.

Updates commit 7eb219d193.

Thanks: Laszlo Ersek.
This commit is contained in:
Richard W.M. Jones
2017-04-05 13:44:00 +01:00
parent 95f1e83baf
commit 413ebec039
3 changed files with 11 additions and 7 deletions

View File

@@ -397,7 +397,7 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
(* Check a non-Xen kernel exists. *)
let only_xen_kernels = List.for_all (
fun { ki_is_xen_kernel = is_xen_kernel } -> is_xen_kernel
fun { ki_is_xen_pv_only_kernel = pv_only } -> pv_only
) bootloader_kernels in
if only_xen_kernels then
error (f_"only Xen kernels are installed in this guest.\n\nRead the %s(1) manual, section \"XEN PARAVIRTUALIZED GUESTS\", to see what to do.") prog;
@@ -417,7 +417,9 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
)
in
let kernels = bootloader_kernels in
let kernels = List.filter (fun { ki_is_xen_kernel = is_xen_kernel } -> not is_xen_kernel) kernels in
let kernels =
List.filter (fun { ki_is_xen_pv_only_kernel = pv_only } -> not pv_only)
kernels in
let kernels = List.sort compare_best_kernels kernels in
let kernels = List.rev kernels (* so best is first *) in
List.hd kernels in

View File

@@ -39,7 +39,7 @@ type kernel_info = {
ki_modpath : string;
ki_modules : string list;
ki_supports_virtio : bool;
ki_is_xen_kernel : bool;
ki_is_xen_pv_only_kernel : bool;
ki_is_debug : bool;
ki_config_file : string option;
}
@@ -49,7 +49,7 @@ let string_of_kernel_info ki =
ki.ki_name ki.ki_version ki.ki_arch ki.ki_vmlinuz
(match ki.ki_initrd with None -> "None" | Some f -> f)
(match ki.ki_config_file with None -> "None" | Some f -> f)
ki.ki_supports_virtio ki.ki_is_xen_kernel ki.ki_is_debug
ki.ki_supports_virtio ki.ki_is_xen_pv_only_kernel ki.ki_is_debug
let detect_kernels (g : G.guestfs) inspect family bootloader =
(* What kernel/kernel-like packages are installed on the current guest? *)
@@ -182,7 +182,9 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
List.mem what modules || check_config kconf config_file in
let supports_virtio = kernel_supports "virtio_net" "VIRTIO_NET" in
let is_xen_kernel = List.mem "xennet" modules in
let is_xen_pv_only_kernel =
check_config "X86_XEN" config_file ||
check_config "X86_64_XEN" config_file in
(* If the package name is like "kernel-debug", then it's
* a debug kernel.
@@ -202,7 +204,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
ki_modpath = modpath;
ki_modules = modules;
ki_supports_virtio = supports_virtio;
ki_is_xen_kernel = is_xen_kernel;
ki_is_xen_pv_only_kernel = is_xen_pv_only_kernel;
ki_is_debug = is_debug;
ki_config_file = config_file;
}

View File

@@ -29,7 +29,7 @@ type kernel_info = {
ki_modpath : string; (** The module path. *)
ki_modules : string list; (** The list of module names. *)
ki_supports_virtio : bool; (** Kernel has virtio drivers? *)
ki_is_xen_kernel : bool; (** Is a Xen paravirt kernel? *)
ki_is_xen_pv_only_kernel : bool; (** Is a Xen paravirt-only kernel? *)
ki_is_debug : bool; (** Is debug kernel? *)
ki_config_file : string option; (** Path of config file, if found. *)
}