[Libguestfs] [PATCH libnbd 1/2] ocaml/examples: Fix extents example

Richard W.M. Jones rjones at redhat.com
Sat Dec 11 13:41:05 UTC 2021


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




More information about the Libguestfs mailing list