On 12/19/22 23:16, Andrey Drobyshev wrote:

> Now I'm a bit confused myself as a result of our discussion: should we
> really give priority to BIOS Boot partition?  Because I tried to
> replay the opposite scenario -- i.e. to convert a disk previously used
> by BIOS machine to be used by UEFI machine, but leaving BIOS Boot
> partition with its parttype unchanged.  And it failed to no surprise
> with this patch applied.  Do you have a clearer understanding of what
> to prioritize and why?

In fact I do have a preference here. I consider this partition table
busted (inconsistent). If not necessarily for booting then for virt-v2v
purposes certainly. As you've showed yourself, if we apply this patch,
then we make things worse for the "inverse busting" of the partition
table.

So I think we should leave this as-is, as far as *automatic* detection
is concerned. We could introduce a command line option for forcing the
source firmware type, but that's something I'd like Rich to comment upon
as well (especially because it is a user interface change), and Rich is
on PTO.

I understand this patch is motivated by a preexistent customer issue
report; I figure the answer we can give, thus far, is "your source
system is inconsistent enough that we can't safely/robustly judge what
to do with it in an automated fashion".

>>>> (5) I don't really like the runtime logic duplication that seems to
>>>> be introduced by the patch. By iterating over the list of
>>>> partitions twice, we make twice as many libguestfs calls. I think
>>>> we should iterate only once over the list of partitions.
>>>
>>> Agreed, iterating just once is obviously better.  I'll try to come
>>> up with the code which is less obscure.  For instance, List.map with
>>> a custom function, taking partition as its argument and returning a
>>> tuple (Some part * bool).  This way we'd get a list of tuples which
>>> you referred to in your other comment.
>>
>> Can you try out the patches I proposed below?
>>
>> I agree that List.map + List.fold would work, but then (a) you don't
>> need a separate mapping step just so you can fold the mapped list:
>> you can push the mapping down into the folder callback; (b) I
>> honestly doubt in this case that the purely functional implementation
>> would be easier to read. Anyway, if you prefer that, I'm certainly OK
>> with it.
>
> Well, to my view the necessity to use ref's make it a bit clumsy, sort
> of like using global variables where they could've been avoided. Would
> you consider this (functional) use of List.exists, List.filter_map?

I do think that (regarless of real life utility) this is a very
interesting discussion. So you've now prompted me to rewrite the patches
without refs, just for my own interest.

I think we can do it more compactly than List.exists (for the bios boot
part) *plus* List.filter_map (for the ESP part list).

First patch (refactoring, purely functional style, using
"Array.fold_left"):

> diff --git a/convert/inspect_source.ml b/convert/inspect_source.ml
> index 056d0bca62e6..9686f9fff8d8 100644
> --- a/convert/inspect_source.ml
> +++ b/convert/inspect_source.ml
> @@ -225,26 +225,29 @@ and list_applications g root = function
>   * Otherwise, [BIOS] is returned.
>   *)
>  and get_firmware_bootable_device g =
> -  let rec uefi_ESP_guid = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
> -  and is_uefi_ESP dev part =
> -    let partnum = g#part_to_partnum part in
> -    g#part_get_gpt_type dev partnum = uefi_ESP_guid
> -  and parttype_is_gpt dev =
> +  let parttype_is_gpt dev =
>      try g#part_get_parttype dev = "gpt"
>      with G.Error msg as exn ->
>           (* If it's _not_ "unrecognised disk label" then re-raise it. *)
>           if g#last_errno () <> G.Errno.errno_EINVAL then raise exn;
>           debug "%s (ignored)" msg;
>           false
> -  and is_uefi_bootable_part part =
> +  in
> +  let accumulate_partition esp_parts part =
>      let dev = g#part_to_dev part in
> -    parttype_is_gpt dev && is_uefi_ESP dev part
> +    if parttype_is_gpt dev then
> +      let partnum = g#part_to_partnum part in
> +      let part_type_guid = g#part_get_gpt_type dev partnum in
> +      match part_type_guid with
> +      | "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" -> part :: esp_parts
> +      | _ -> esp_parts
> +    else esp_parts
>    in
>
> -  let partitions = Array.to_list (g#list_partitions ()) in
> -  let partitions = List.filter is_uefi_bootable_part partitions in
> +  let esp_partitions =
> +    Array.fold_left accumulate_partition [] (g#list_partitions ()) in
>
> -  match partitions with
> +  match esp_partitions with
>    | [] -> I_BIOS
>    | partitions -> I_UEFI partitions
>

Second patch (adding bios_boot):

> diff --git a/convert/inspect_source.ml b/convert/inspect_source.ml
> index 9686f9fff8d8..8e8f5c45f1eb 100644
> --- a/convert/inspect_source.ml
> +++ b/convert/inspect_source.ml
> @@ -233,23 +233,24 @@ and get_firmware_bootable_device g =
>           debug "%s (ignored)" msg;
>           false
>    in
> -  let accumulate_partition esp_parts part =
> +  let accumulate_partition (esp_parts, bboot) part =
>      let dev = g#part_to_dev part in
>      if parttype_is_gpt dev then
>        let partnum = g#part_to_partnum part in
>        let part_type_guid = g#part_get_gpt_type dev partnum in
>        match part_type_guid with
> -      | "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" -> part :: esp_parts
> -      | _ -> esp_parts
> -    else esp_parts
> +      | "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" -> part :: esp_parts, bboot
> +      | "21686148-6449-6E6F-744E-656564454649" -> esp_parts, true
> +      | _ -> esp_parts, bboot
> +    else esp_parts, bboot
>    in
>
> -  let esp_partitions =
> -    Array.fold_left accumulate_partition [] (g#list_partitions ()) in
> +  let esp_partitions, bios_boot =
> +    Array.fold_left accumulate_partition ([], false) (g#list_partitions ()) 
> in
>
> -  match esp_partitions with
> -  | [] -> I_BIOS
> -  | partitions -> I_UEFI partitions
> +  match esp_partitions, bios_boot with
> +  | _ :: _, false -> I_UEFI esp_partitions
> +  | _ -> I_BIOS
>
>  (* If some inspection fields are "unknown", then that indicates a
>   * failure in inspection, and we shouldn't continue.  For an example

You be the judge whether this is easier to read then the reference cells
version :)

Laszlo
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to