Re: [Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-07 Thread Andrey Drobyshev
On 3/6/23 18:52, Richard W.M. Jones wrote:
> This is just an outline patch, only compile tested.
> 
> It doesn't make changes to virt-v2v-in-place, but those would be the
> same as made in v2v/v2v.ml.
> 
> It reuses the existing Types.guestcaps_block_type which is a bit ugly
> but fairly practical.
> 
> I've made the change to the documentation, but it needs a test.
> 
> Rich.
> 

Thanks for the provided outlines, I adapted them in my v2:

https://listman.redhat.com/archives/libguestfs/2023-March/030987.html
https://listman.redhat.com/archives/libguestfs/2023-March/030989.html

I have tested the in-place mode, and the switch seems to be working as
expected.

The patch also adds the convert option to the virt-v2v-inspector tool as
it's also using the conversion mechanism.  I figured that this cmdline
switch isn't much needed there, so the option is set just for avoiding
compilation issues.

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



Re: [Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-07 Thread Richard W.M. Jones
On Tue, Mar 07, 2023 at 11:26:37AM +0100, Laszlo Ersek wrote:
> On 3/7/23 09:35, Richard W.M. Jones wrote:
> > On Tue, Mar 07, 2023 at 08:48:56AM +0100, Laszlo Ersek wrote:
> >> On 3/6/23 17:52, Richard W.M. Jones wrote:
> >>
> >>> diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
> >>> index 9d8d271d05..f36b486359 100644
> >>> --- a/convert/convert_windows.ml
> >>> +++ b/convert/convert_windows.ml
> >>> @@ -38,7 +38,7 @@ module G = Guestfs
> >>>   * time the Windows VM is booted on KVM.
> >>>   *)
> >>>  
> >>> -let convert (g : G.guestfs) _ inspect i_firmware _ static_ips =
> >>> +let convert (g : G.guestfs) _ inspect i_firmware block_driver _ 
> >>> static_ips =
> >>>
> >>> (*--*)
> >>>(* Inspect the Windows guest. *)
> >>>  
> >>> @@ -47,6 +47,16 @@ let convert (g : G.guestfs) _ inspect i_firmware _ 
> >>> static_ips =
> >>> *)
> >>>let virtio_win =
> >>>  Inject_virtio_win.from_environment g inspect.i_root Config.datadir in
> >>> +  (match block_driver with
> >>> +   | Virtio_blk -> () (* the default, no need to do anything *)
> >>> +(*
> >>> +   | Virtio_scsi ->
> >>> +  let drivers = Inject_virtio_win.get_block_driver_priority 
> >>> virtio_win in
> >>> +  let drivers = "vioscsi" :: drivers in
> >>> +  Inject_virtio_win.set_block_driver_priority virtio_win drivers
> >>> +*)
> >>> +   | IDE -> assert false (* not possible - but maybe ...? *)
> >>> +  );
> >>>  
> >>>(* If the Windows guest appears to be using group policy.
> >>> *
> >>
> >> So ["virtio_blk"; "vrtioblk"; "viostor"] in
> >> "common/mlcustomize/inject_virtio_win.ml" would be replaced with a
> >> reference cell, and get_block_driver_priority /
> >> set_block_driver_priority would manipulate that.
> > 
> > References are really just structures with mutable fields and some
> > syntactic sugar:
> > 
> > https://github.com/ocaml/ocaml/blob/66db964f48869c6470b8ccd1ed672e244ba9d680/stdlib/stdlib.ml#L237
> > 
> > The reason mutable fields of structures in general have to be
> > specially marked with the "mutable" keyword is because of the
> > "remembered set", an obscure corner of generational garbage collection:
> > 
> > https://www.cs.cornell.edu/courses/cs3110/2012sp/lectures/lec26-gc/lec26.html
> > 
> > If mutable fields didn't exist then you could never have a pointer
> > from the old generation into the new generation, because new
> > generation objects are always younger than old generation objects, and
> > as all fields have to be set at object creation time (no mutation),
> > there cannot exist pointers from old to new.
> > 
> > Since mutable fields _do_ exist, it's possible for such pointers to
> > exist.  When you do a minor GC of the younger generation, to avoid
> > having to scan over the whole of the old heap to find these pointers,
> > when a mutable field is mutated a record is added to the "remembered
> > set", which is treated as an additional set of roots for the minor GC.
> > 
> > After each minor GC the remembered set can be cleared.
> 
> Why is that?
>
> If the "remembered" objects remain in the young generation, still only
> referenced by objects of the old generation, then the extra roots
> pointing to these young objects should persist, shouldn't they? A young
> object can be removed from the remembered set when it transitions to the
> old generation at the same time -- but that need not happen at each GC
> run over the young generation. IIUC.

When you do a minor GC you're moving all the still referenced objects
from the minor heap ("young generation") into the major heap ("old
generation").  Therefore they just become objects in the old
generation where they can all reference each other, not distinguished
by age, and that is all handled by a different algorithm (mark-sweep-compact).

Meanwhile the minor heap, which is basically a single fixed-sized area
of memory that allocations come from is reset.

Thus the remembered set is no longer needed and can be cleared.

This is for the simple two generation case as used by OCaml.  Golang
uses a non-generational collector.  Java uses a multi-generation
system where they have remembered sets for each generation ("region"
in Java-GC-speak), and they also use a slightly different algorithm
for the remembered set called "card table" but it solves the same
problem.

BTW I found a page which describes the OCaml collector and benchmarks
the overhead of mutable structs and has the discussion of the
trade-offs involved (in short, mutable algorithms have less
allocation, but the allocations have more overhead because of the
remembered set):

https://dev.realworldocaml.org/garbage-collector.html#scrollNav-4-5

Rich.

> > But there's
> > still some overhead here, so marking fields in a struct as mutable is
> > not cost free.  (Of course in this specific case the cost is
> > infinitesimally small, but in general it can be a concern.)
> > 
> > This is a long way o

Re: [Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-07 Thread Laszlo Ersek
On 3/7/23 09:35, Richard W.M. Jones wrote:
> On Tue, Mar 07, 2023 at 08:48:56AM +0100, Laszlo Ersek wrote:
>> On 3/6/23 17:52, Richard W.M. Jones wrote:
>>
>>> diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
>>> index 9d8d271d05..f36b486359 100644
>>> --- a/convert/convert_windows.ml
>>> +++ b/convert/convert_windows.ml
>>> @@ -38,7 +38,7 @@ module G = Guestfs
>>>   * time the Windows VM is booted on KVM.
>>>   *)
>>>  
>>> -let convert (g : G.guestfs) _ inspect i_firmware _ static_ips =
>>> +let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips 
>>> =
>>>
>>> (*--*)
>>>(* Inspect the Windows guest. *)
>>>  
>>> @@ -47,6 +47,16 @@ let convert (g : G.guestfs) _ inspect i_firmware _ 
>>> static_ips =
>>> *)
>>>let virtio_win =
>>>  Inject_virtio_win.from_environment g inspect.i_root Config.datadir in
>>> +  (match block_driver with
>>> +   | Virtio_blk -> () (* the default, no need to do anything *)
>>> +(*
>>> +   | Virtio_scsi ->
>>> +  let drivers = Inject_virtio_win.get_block_driver_priority virtio_win 
>>> in
>>> +  let drivers = "vioscsi" :: drivers in
>>> +  Inject_virtio_win.set_block_driver_priority virtio_win drivers
>>> +*)
>>> +   | IDE -> assert false (* not possible - but maybe ...? *)
>>> +  );
>>>  
>>>(* If the Windows guest appears to be using group policy.
>>> *
>>
>> So ["virtio_blk"; "vrtioblk"; "viostor"] in
>> "common/mlcustomize/inject_virtio_win.ml" would be replaced with a
>> reference cell, and get_block_driver_priority /
>> set_block_driver_priority would manipulate that.
> 
> References are really just structures with mutable fields and some
> syntactic sugar:
> 
> https://github.com/ocaml/ocaml/blob/66db964f48869c6470b8ccd1ed672e244ba9d680/stdlib/stdlib.ml#L237
> 
> The reason mutable fields of structures in general have to be
> specially marked with the "mutable" keyword is because of the
> "remembered set", an obscure corner of generational garbage collection:
> 
> https://www.cs.cornell.edu/courses/cs3110/2012sp/lectures/lec26-gc/lec26.html
> 
> If mutable fields didn't exist then you could never have a pointer
> from the old generation into the new generation, because new
> generation objects are always younger than old generation objects, and
> as all fields have to be set at object creation time (no mutation),
> there cannot exist pointers from old to new.
> 
> Since mutable fields _do_ exist, it's possible for such pointers to
> exist.  When you do a minor GC of the younger generation, to avoid
> having to scan over the whole of the old heap to find these pointers,
> when a mutable field is mutated a record is added to the "remembered
> set", which is treated as an additional set of roots for the minor GC.
> 
> After each minor GC the remembered set can be cleared.

Why is that?

If the "remembered" objects remain in the young generation, still only
referenced by objects of the old generation, then the extra roots
pointing to these young objects should persist, shouldn't they? A young
object can be removed from the remembered set when it transitions to the
old generation at the same time -- but that need not happen at each GC
run over the young generation. IIUC.

> But there's
> still some overhead here, so marking fields in a struct as mutable is
> not cost free.  (Of course in this specific case the cost is
> infinitesimally small, but in general it can be a concern.)
> 
> This is a long way of saying that it's not a reference cell, but a
> plain field in the 't' struct, with extra runtime overhead and code
> generated for when it is mutated.

Thanks!
Laszlo

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



Re: [Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-07 Thread Richard W.M. Jones
On Tue, Mar 07, 2023 at 08:48:56AM +0100, Laszlo Ersek wrote:
> On 3/6/23 17:52, Richard W.M. Jones wrote:
> 
> > diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
> > index 9d8d271d05..f36b486359 100644
> > --- a/convert/convert_windows.ml
> > +++ b/convert/convert_windows.ml
> > @@ -38,7 +38,7 @@ module G = Guestfs
> >   * time the Windows VM is booted on KVM.
> >   *)
> >  
> > -let convert (g : G.guestfs) _ inspect i_firmware _ static_ips =
> > +let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips 
> > =
> >
> > (*--*)
> >(* Inspect the Windows guest. *)
> >  
> > @@ -47,6 +47,16 @@ let convert (g : G.guestfs) _ inspect i_firmware _ 
> > static_ips =
> > *)
> >let virtio_win =
> >  Inject_virtio_win.from_environment g inspect.i_root Config.datadir in
> > +  (match block_driver with
> > +   | Virtio_blk -> () (* the default, no need to do anything *)
> > +(*
> > +   | Virtio_scsi ->
> > +  let drivers = Inject_virtio_win.get_block_driver_priority virtio_win 
> > in
> > +  let drivers = "vioscsi" :: drivers in
> > +  Inject_virtio_win.set_block_driver_priority virtio_win drivers
> > +*)
> > +   | IDE -> assert false (* not possible - but maybe ...? *)
> > +  );
> >  
> >(* If the Windows guest appears to be using group policy.
> > *
> 
> So ["virtio_blk"; "vrtioblk"; "viostor"] in
> "common/mlcustomize/inject_virtio_win.ml" would be replaced with a
> reference cell, and get_block_driver_priority /
> set_block_driver_priority would manipulate that.

References are really just structures with mutable fields and some
syntactic sugar:

https://github.com/ocaml/ocaml/blob/66db964f48869c6470b8ccd1ed672e244ba9d680/stdlib/stdlib.ml#L237

The reason mutable fields of structures in general have to be
specially marked with the "mutable" keyword is because of the
"remembered set", an obscure corner of generational garbage collection:

https://www.cs.cornell.edu/courses/cs3110/2012sp/lectures/lec26-gc/lec26.html

If mutable fields didn't exist then you could never have a pointer
from the old generation into the new generation, because new
generation objects are always younger than old generation objects, and
as all fields have to be set at object creation time (no mutation),
there cannot exist pointers from old to new.

Since mutable fields _do_ exist, it's possible for such pointers to
exist.  When you do a minor GC of the younger generation, to avoid
having to scan over the whole of the old heap to find these pointers,
when a mutable field is mutated a record is added to the "remembered
set", which is treated as an additional set of roots for the minor GC.

After each minor GC the remembered set can be cleared.  But there's
still some overhead here, so marking fields in a struct as mutable is
not cost free.  (Of course in this specific case the cost is
infinitesimally small, but in general it can be a concern.)

This is a long way of saying that it's not a reference cell, but a
plain field in the 't' struct, with extra runtime overhead and code
generated for when it is mutated.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v
___
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs



Re: [Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-06 Thread Laszlo Ersek
On 3/6/23 17:52, Richard W.M. Jones wrote:

> diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
> index 9d8d271d05..f36b486359 100644
> --- a/convert/convert_windows.ml
> +++ b/convert/convert_windows.ml
> @@ -38,7 +38,7 @@ module G = Guestfs
>   * time the Windows VM is booted on KVM.
>   *)
>  
> -let convert (g : G.guestfs) _ inspect i_firmware _ static_ips =
> +let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
>(*--*)
>(* Inspect the Windows guest. *)
>  
> @@ -47,6 +47,16 @@ let convert (g : G.guestfs) _ inspect i_firmware _ 
> static_ips =
> *)
>let virtio_win =
>  Inject_virtio_win.from_environment g inspect.i_root Config.datadir in
> +  (match block_driver with
> +   | Virtio_blk -> () (* the default, no need to do anything *)
> +(*
> +   | Virtio_scsi ->
> +  let drivers = Inject_virtio_win.get_block_driver_priority virtio_win in
> +  let drivers = "vioscsi" :: drivers in
> +  Inject_virtio_win.set_block_driver_priority virtio_win drivers
> +*)
> +   | IDE -> assert false (* not possible - but maybe ...? *)
> +  );
>  
>(* If the Windows guest appears to be using group policy.
> *

So ["virtio_blk"; "vrtioblk"; "viostor"] in
"common/mlcustomize/inject_virtio_win.ml" would be replaced with a
reference cell, and get_block_driver_priority /
set_block_driver_priority would manipulate that.

This looks OK to me.

That said, I'd prefer that this patch be split up a bit (by Andrey).
Patch#1 could introduce the new field and make sure it is passed around
(incl. setting the default virtio-blk value); that's purely boilerplate,
so the patch would be well-focused. Patch #2 could glue the new field to
the new Inject_virtio_win APIs, in "convert_windows.ml". Patch#3 could
implement the command line changes and update the documentation.

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



[Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-06 Thread Richard W.M. Jones
---
 docs/virt-v2v.pod   | 10 ++
 convert/convert.mli |  1 +
 convert/convert_linux.mli   |  3 ++-
 convert/convert_windows.mli |  3 ++-
 convert/convert.ml  |  9 ++---
 convert/convert_linux.ml|  2 +-
 convert/convert_windows.ml  | 12 +++-
 in-place/in_place.ml|  3 ++-
 inspector/inspector.ml  |  3 ++-
 v2v/v2v.ml  | 12 +++-
 10 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
index b458607d14..e096418b2c 100644
--- a/docs/virt-v2v.pod
+++ b/docs/virt-v2v.pod
@@ -207,6 +207,16 @@ The options are silently ignored for other input methods.
 
 See I<--network> below.
 
+=item B<--block-driver virtio-blk>
+
+=item B<--block-driver virtio-scsi>
+
+When choosing a block driver for Windows guests, prefer C or
+C.  The default is C.
+
+Note this has no effect for Linux guests at the moment.  That may be
+added in future.
+
 =item B<--colors>
 
 =item B<--colours>
diff --git a/convert/convert.mli b/convert/convert.mli
index 3bd39e2da8..c63bf6f0da 100644
--- a/convert/convert.mli
+++ b/convert/convert.mli
@@ -17,6 +17,7 @@
  *)
 
 type options = {
+  block_driver : Types.guestcaps_block_type; (** [--block-driver] option *)
   keep_serial_console : bool;
   ks : Tools_utils.key_store;  (** [--key] option *)
   network_map : Networks.t;(** [-b] and [-n] options *)
diff --git a/convert/convert_linux.mli b/convert/convert_linux.mli
index 6eb272e9b4..dc6968fe51 100644
--- a/convert/convert_linux.mli
+++ b/convert/convert_linux.mli
@@ -23,5 +23,6 @@
 Mint and Kali are supported by this module. *)
 
 val convert : Guestfs.guestfs -> Types.source -> Types.inspect ->
-  Firmware.i_firmware -> bool -> Types.static_ip list ->
+  Firmware.i_firmware -> Types.guestcaps_block_type ->
+  bool -> Types.static_ip list ->
   Types.guestcaps
diff --git a/convert/convert_windows.mli b/convert/convert_windows.mli
index 42dac9f50c..33a14f6596 100644
--- a/convert/convert_windows.mli
+++ b/convert/convert_windows.mli
@@ -21,5 +21,6 @@
 This module converts a Windows guest to run on KVM. *)
 
 val convert : Guestfs.guestfs -> Types.source -> Types.inspect ->
-  Firmware.i_firmware -> bool -> Types.static_ip list ->
+  Firmware.i_firmware -> Types.guestcaps_block_type ->
+  bool -> Types.static_ip list ->
   Types.guestcaps
diff --git a/convert/convert.ml b/convert/convert.ml
index 0aa0e5cd3c..fa34d2ed7f 100644
--- a/convert/convert.ml
+++ b/convert/convert.ml
@@ -31,6 +31,7 @@ open Utils
 module G = Guestfs
 
 type options = {
+  block_driver : guestcaps_block_type;
   keep_serial_console : bool;
   ks : key_store;
   network_map : Networks.t;
@@ -88,7 +89,7 @@ let rec convert dir options source =
   (* Conversion. *)
   let guestcaps =
 do_convert g source inspect i_firmware
-  options.keep_serial_console options.static_ips in
+  options.block_driver options.keep_serial_console options.static_ips in
 
   g#umount_all ();
 
@@ -221,7 +222,8 @@ and do_fstrim g inspect =
   ) fses
 
 (* Conversion. *)
-and do_convert g source inspect i_firmware keep_serial_console interfaces =
+and do_convert g source inspect i_firmware
+   block_driver keep_serial_console interfaces =
   (match inspect.i_product_name with
   | "unknown" ->
 message (f_"Converting the guest to run on KVM")
@@ -246,7 +248,8 @@ and do_convert g source inspect i_firmware 
keep_serial_console interfaces =
  inspect.i_type inspect.i_distro in
   debug "picked conversion module %s" conversion_name;
   let guestcaps =
-convert g source inspect i_firmware keep_serial_console interfaces in
+convert g source inspect i_firmware
+block_driver keep_serial_console interfaces in
   debug "%s" (string_of_guestcaps guestcaps);
 
   (* Did we manage to install virtio drivers? *)
diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml
index d5c0f24dbb..0f25af0eab 100644
--- a/convert/convert_linux.ml
+++ b/convert/convert_linux.ml
@@ -34,7 +34,7 @@ open Linux_kernels
 module G = Guestfs
 
 (* The conversion function. *)
-let convert (g : G.guestfs) source inspect i_firmware keep_serial_console _ =
+let convert (g : G.guestfs) source inspect i_firmware _ keep_serial_console _ =
   (*--*)
   (* Inspect the guest first.  We already did some basic inspection in
* the common v2v.ml code, but that has to deal with generic guests
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
index 9d8d271d05..f36b486359 100644
--- a/convert/convert_windows.ml
+++ b/convert/convert_windows.ml
@@ -38,7 +38,7 @@ module G = Guestfs
  * time the Windows VM is booted on KVM.
  *)
 
-let convert (g : G.guestfs) _ inspect i_firmware _ static_ips =
+let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ip

[Libguestfs] [PATCH v2v] convert: Allow preferred block driver to be specified on the command line

2023-03-06 Thread Richard W.M. Jones
This is just an outline patch, only compile tested.

It doesn't make changes to virt-v2v-in-place, but those would be the
same as made in v2v/v2v.ml.

It reuses the existing Types.guestcaps_block_type which is a bit ugly
but fairly practical.

I've made the change to the documentation, but it needs a test.

Rich.


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