Laszlo Ersek noted that the original example we had did not work properly if the size of the disk was larger than around 2G.
The nbd_block_status API is really difficult to use correctly! In particular it is not guaranteed that the server will return extents covering the size requested. It's also not guaranteed that a bad server will return any base:allocation extents at all (although such a server would not be conforming - the protocol says that servers must always make forward progress). This commit attempts a fix, although it is not complete especially if the server is badly behaved. It also makes the output look a bit better by aligning the columns. Also we use nbdkit-sparse-random- plugin with a larger size to test the > 2G case. --- ocaml/examples/extents.ml | 53 ++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/ocaml/examples/extents.ml b/ocaml/examples/extents.ml index 6fa70e087..e4422b270 100644 --- a/ocaml/examples/extents.ml +++ b/ocaml/examples/extents.ml @@ -4,32 +4,33 @@ let () = let nbd = NBD.create () in NBD.add_meta_context nbd "base:allocation"; NBD.connect_command nbd - ["nbdkit"; "-s"; "--exit-with-parent"; "memory"; "size=128K"]; - - (* Write some sectors. *) - let data_sector = Bytes.make 512 'a' in - let zero_sector = Bytes.make 512 '\000' in - NBD.pwrite nbd data_sector 0_L; - NBD.pwrite nbd zero_sector 32768_L; - NBD.pwrite nbd data_sector 65536_L; + ["nbdkit"; "-s"; "--exit-with-parent"; "-r"; + "sparse-random"; "8G"]; (* Read the extents and print them. *) let size = NBD.get_size nbd in - NBD.block_status nbd size 0_L ( - fun meta _ entries err -> - printf "err=%d\n" !err; - if meta = "base:allocation" then ( - printf "index\tlength\tflags\n"; - for i = 0 to Array.length entries / 2 - 1 do - let flags = - match entries.(i*2+1) with - | 0_l -> "data" - | 1_l -> "hole" - | 2_l -> "zero" - | 3_l -> "hole+zero" - | i -> sprintf "unknown (%ld)" i in - printf "%d:\t%ld\t%s\n" i entries.(i*2) flags - done - ); - 0 - ) + let fetch_offset = ref 0_L in + while !fetch_offset < size do + let remaining = Int64.sub size !fetch_offset in + let fetch_size = min remaining 0x8000_0000_L in + NBD.block_status nbd fetch_size !fetch_offset ( + fun meta _ entries err -> + printf "nbd_block_status callback: meta=%s err=%d\n" meta !err; + if meta = "base:allocation" then ( + printf "index\t%-20s %-20s %s\n" "offset" "length" "flags"; + for i = 0 to Array.length entries / 2 - 1 do + let len = Int64.of_int32 entries.(i*2) + and flags = + match entries.(i*2+1) with + | 0_l -> "data" + | 1_l -> "hole" + | 2_l -> "zero" + | 3_l -> "hole+zero" + | i -> sprintf "unknown (%ld)" i in + printf "%d:\t%-20Ld %-20Ld %s\n" i !fetch_offset len flags; + fetch_offset := Int64.add !fetch_offset len + done; + ); + 0 + ) (* NBD.block_status *) + done -- 2.32.0 _______________________________________________ Libguestfs mailing list [email protected] https://listman.redhat.com/mailman/listinfo/libguestfs
