@@ -42,6 +42,7 @@
| BytesPersistOut of string * string
| Closure of closure
| Enum of string * enum
+| Extent64 of string
| Fd of string
| Flags of string * flags
| Int of string
@@ -157,6 +158,14 @@ let extent_closure =
"nr_entries");
CBMutable (Int "error") ]
}
+let extent64_closure = {
+ cbname = "extent64";
+ cbargs = [ CBString "metacontext";
+ CBUInt64 "offset";
+ CBArrayAndLen (Extent64 "entries",
+ "nr_entries");
+ CBMutable (Int "error") ]
+}
let list_closure = {
cbname = "list";
cbargs = [ CBString "name"; CBString "description" ]
@@ -166,7 +175,8 @@ let context_closure =
cbargs = [ CBString "name" ]
}
let all_closures = [ chunk_closure; completion_closure;
- debug_closure; extent_closure; list_closure;
+ debug_closure; extent_closure; extent64_closure;
+ list_closure;
context_closure ]
(* Enums. *)
@@ -52,6 +52,7 @@ and
| BytesPersistOut of string * string
| Closure of closure (** function pointer + void *opaque *)
| Enum of string * enum (** enum/union type, int in C *)
+| Extent64 of string (** extent descriptor, struct nbd_extent in C *)
| Fd of string (** file descriptor *)
| Flags of string * flags (** flags, uint32_t in C *)
| Int of string (** small int *)
@@ -93,6 +93,7 @@ let
| Closure { cbname } ->
[ sprintf "%s_callback" cbname; sprintf "%s_user_data" cbname ]
| Enum (n, _) -> [n]
+ | Extent64 n -> [n]
| Fd n -> [n]
| Flags (n, _) -> [n]
| Int n -> [n]
@@ -128,7 +129,7 @@ let
(* list of strings should be marked as non-null *)
| StringList n -> [ true ]
(* numeric and other non-pointer types are not able to be null *)
- | Bool _ | Closure _ | Enum _ | Fd _ | Flags _
+ | Bool _ | Closure _ | Enum _ | Extent64 _ | Fd _ | Flags _
| Int _ | Int64 _ | SizeT _
| UInt _ | UInt32 _ | UInt64 _ | UIntPtr _ -> [ false ]
@@ -182,6 +183,9 @@ and
| Enum (n, _) ->
if types then pr "int ";
pr "%s" n
+ | Extent64 n ->
+ if types then pr "nbd_extent ";
+ pr "%s" n
| Flags (n, _) ->
if types then pr "uint32_t ";
pr "%s" n
@@ -292,6 +296,11 @@ and
pr "%s, " n;
if types then pr "size_t ";
pr "%s" len
+ | CBArrayAndLen (Extent64 n, len) ->
+ if types then pr "nbd_extent *";
+ pr "%s, " n;
+ if types then pr "size_t ";
+ pr "%s" len
| CBArrayAndLen _ -> assert false
| CBBytesIn (n, len) ->
if types then pr "const void *";
@@ -463,6 +472,13 @@ let
pr "extern int nbd_get_errno (void);\n";
pr "#define LIBNBD_HAVE_NBD_GET_ERRNO 1\n";
pr "\n";
+ pr "/* This is used in the callback for nbd_block_status_64.\n";
+ pr " */\n";
+ pr "typedef struct {\n";
+ pr " uint64_t length;\n";
+ pr " uint64_t flags;\n";
+ pr "} nbd_extent;\n";
+ pr "\n";
print_closure_structs ();
List.iter (
fun (name, { args; optargs; ret }) ->
@@ -716,7 +732,7 @@ let
pr " char *%s_printable =\n" n;
pr " nbd_internal_printable_string_list (%s);\n" n
| BytesOut _ | BytesPersistOut _
- | Bool _ | Closure _ | Enum _ | Flags _ | Fd _ | Int _
+ | Bool _ | Closure _ | Enum _ | Extent64 _ | Flags _ | Fd _ | Int _
| Int64 _ | SizeT _
| SockAddrAndLen _ | UInt _ | UInt32 _ | UInt64 _ | UIntPtr _ -> ()
) args;
@@ -735,6 +751,7 @@ let
pr " %s=\\\"%%s\\\" %s=%%zu" n count
| Closure { cbname } -> pr " %s=<fun>" cbname
| Enum (n, _) -> pr " %s=%%d" n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Flags (n, _) -> pr " %s=0x%%x" n
| Fd n | Int n -> pr " %s=%%d" n
| Int64 n -> pr " %s=%%\" PRIi64 \"" n
@@ -764,6 +781,7 @@ let
pr ", %s_printable ? %s_printable : \"\", %s" n n count
| Closure { cbname } -> ()
| Enum (n, _) -> pr ", %s" n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Flags (n, _) -> pr ", %s" n
| Fd n | Int n | Int64 n | SizeT n -> pr ", %s" n
| SockAddrAndLen (_, len) -> pr ", (int) %s" len
@@ -787,7 +805,7 @@ let
| StringList n ->
pr " free (%s_printable);\n" n
| BytesOut _ | BytesPersistOut _
- | Bool _ | Closure _ | Enum _ | Flags _ | Fd _ | Int _
+ | Bool _ | Closure _ | Enum _ | Extent64 _ | Flags _ | Fd _ | Int _
| Int64 _ | SizeT _
| SockAddrAndLen _ | UInt _ | UInt32 _ | UInt64 _ | UIntPtr _ -> ()
) args;
@@ -49,6 +49,7 @@ let
| BytesPersistOut (n, len) -> n
| Closure { cbname } -> cbname
| Enum (n, _) -> n
+ | Extent64 n -> n
| Fd n -> n
| Flags (n, _) -> n
| Int n -> n
@@ -71,6 +72,7 @@ let
| BytesPersistOut _ -> "AioBuffer"
| Closure { cbname } -> sprintf "%sCallback" (camel_case cbname)
| Enum (_, { enum_prefix }) -> camel_case enum_prefix
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Fd _ -> "int"
| Flags (_, { flag_prefix }) -> camel_case flag_prefix
| Int _ -> "int"
@@ -262,6 +264,7 @@ let
pr " c_%s.user_data = C.alloc_cbid(C.long(%s_cbid))\n" cbname cbname
| Enum (n, _) ->
pr " c_%s := C.int (%s)\n" n n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Fd n ->
pr " c_%s := C.int (%s)\n" n n
| Flags (n, _) ->
@@ -334,6 +337,7 @@ let
| BytesPersistOut (n, len) -> pr ", c_%s, c_%s" n len
| Closure { cbname } -> pr ", c_%s" cbname
| Enum (n, _) -> pr ", c_%s" n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Fd n -> pr ", c_%s" n
| Flags (n, _) -> pr ", c_%s" n
| Int n -> pr ", c_%s" n
@@ -524,6 +528,18 @@ let
copy(ret, s)
return ret
}
+
+func copy_extent_array (entries *C.nbd_extent, count C.size_t) []LibnbdExtent {
+ unsafePtr := unsafe.Pointer(entries)
+ arrayPtr := (*[1 << 20]C.nbd_extent)(unsafePtr)
+ slice := arrayPtr[:count:count]
+ ret := make([]LibnbdExtent, count)
+ for i := 0; i < int (count); i++ {
+ ret[i].Length = uint64 (slice[i].length)
+ ret[i].Flags = uint64 (slice[i].flags)
+ }
+ return ret
+}
";
List.iter (
@@ -537,6 +553,8 @@ let
match cbarg with
| CBArrayAndLen (UInt32 n, _) ->
pr "%s []uint32" n;
+ | CBArrayAndLen (Extent64 n, _) ->
+ pr "%s []LibnbdExtent" n;
| CBBytesIn (n, len) ->
pr "%s []byte" n;
| CBInt n ->
@@ -563,6 +581,8 @@ let
match cbarg with
| CBArrayAndLen (UInt32 n, count) ->
pr "%s *C.uint32_t, %s C.size_t" n count
+ | CBArrayAndLen (Extent64 n, count) ->
+ pr "%s *C.nbd_extent, %s C.size_t" n count
| CBBytesIn (n, len) ->
pr "%s unsafe.Pointer, %s C.size_t" n len
| CBInt n ->
@@ -605,6 +625,8 @@ let
match cbarg with
| CBArrayAndLen (UInt32 n, count) ->
pr "copy_uint32_array (%s, %s)" n count
+ | CBArrayAndLen (Extent64 n, count) ->
+ pr "copy_extent_array (%s, %s)" n count
| CBBytesIn (n, len) ->
pr "C.GoBytes (%s, C.int (%s))" n len
| CBInt n ->
@@ -756,6 +778,8 @@ let
match cbarg with
| CBArrayAndLen (UInt32 n, count) ->
pr "uint32_t *%s, size_t %s" n count
+ | CBArrayAndLen (Extent64 n, count) ->
+ pr "nbd_extent *%s, size_t %s" n count
| CBBytesIn (n, len) ->
pr "void *%s, size_t %s" n len
| CBInt n ->
@@ -44,6 +44,7 @@ and
| Closure { cbargs } ->
sprintf "(%s)" (ocaml_closuredecl_to_string cbargs)
| Enum (_, { enum_prefix }) -> sprintf "%s.t" enum_prefix
+ | Extent64 _ -> "extent"
| Fd _ -> "Unix.file_descr"
| Flags (_, { flag_prefix }) -> sprintf "%s.t list" flag_prefix
| Int _ -> "int"
@@ -102,6 +103,7 @@ let
| BytesPersistOut (n, len) -> n
| Closure { cbname } -> cbname
| Enum (n, _) -> n
+ | Extent64 n -> n
| Fd n -> n
| Flags (n, _) -> n
| Int n -> n
@@ -147,6 +149,9 @@ let
type cookie = int64
+type extent = int64 * int64
+(** Length and flags of an extent in block_status_64 callback. *)
+
";
List.iter (
@@ -268,6 +273,7 @@ let
exception Error of string * Unix.error option
exception Closed of string
type cookie = int64
+type extent = int64 * int64
(* Give the exceptions names so that they can be raised from the C code. *)
let () =
@@ -498,7 +504,8 @@ let
let argnames =
List.map (
function
- | CBArrayAndLen (UInt32 n, _) | CBBytesIn (n, _)
+ | CBArrayAndLen (UInt32 n, _) | CBArrayAndLen (Extent64 n, _)
+ | CBBytesIn (n, _)
| CBInt n | CBInt64 n
| CBMutable (Int n) | CBString n | CBUInt n | CBUInt64 n ->
n ^ "v"
@@ -526,6 +533,9 @@ let
| CBArrayAndLen (UInt32 n, count) ->
pr " %sv = nbd_internal_ocaml_alloc_int64_from_uint32_array (%s, %s);\n"
n n count;
+ | CBArrayAndLen (Extent64 n, count) ->
+ pr " %sv = nbd_internal_ocaml_alloc_extent64_array (%s, %s);\n"
+ n n count;
| CBBytesIn (n, len) ->
pr " %sv = caml_alloc_initialized_string (%s, %s);\n" n len n
| CBInt n | CBUInt n ->
@@ -549,7 +559,7 @@ let
List.iter (
function
- | CBArrayAndLen (UInt32 _, _)
+ | CBArrayAndLen (_, _)
| CBBytesIn _
| CBInt _
| CBInt64 _
@@ -558,7 +568,7 @@ let
| CBUInt64 _ -> ()
| CBMutable (Int n) ->
pr " *%s = Int_val (Field (%sv, 0));\n" n n
- | CBArrayAndLen _ | CBMutable _ -> assert false
+ | CBMutable _ -> assert false
) cbargs;
pr " if (Is_exception_result (rv)) {\n";
@@ -573,6 +583,7 @@ let
pr "}\n";
pr "\n";
pr "static int\n";
+ pr "__attribute__((unused)) /* XXX temporary hack */\n";
pr "%s_wrapper " cbname;
C.print_cbarg_list ~wrap:true cbargs;
pr "\n";
@@ -688,6 +699,7 @@ let
pr " %s_callback.free = free_user_data;\n" cbname
| Enum (n, { enum_prefix }) ->
pr " int %s = %s_val (%sv);\n" n enum_prefix n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Fd n ->
pr " /* OCaml Unix.file_descr is just an int, at least on Unix. */\n";
pr " int %s = Int_val (%sv);\n" n n
@@ -773,6 +785,7 @@ let
| BytesPersistOut _
| Closure _
| Enum _
+ | Extent64 _
| Fd _
| Flags _
| Int _
@@ -153,6 +153,7 @@ let
let print_python_closure_wrapper { cbname; cbargs } =
pr "/* Wrapper for %s callback. */\n" cbname;
pr "static int\n";
+ pr "__attribute__((unused)) /* XXX temporary hack */\n";
pr "%s_wrapper " cbname;
C.print_cbarg_list ~wrap:true cbargs;
pr "\n";
@@ -165,6 +166,7 @@ let
List.iter (
function
| CBArrayAndLen (UInt32 n, _)
+ | CBArrayAndLen (Extent64 n, _)
| CBBytesIn (n, _)
| CBMutable (Int n) ->
pr " PyObject *py_%s = NULL;\n" n
@@ -182,6 +184,16 @@ let
pr " if (!py_e_%s) { PyErr_PrintEx (0); goto out; }\n" n;
pr " PyList_SET_ITEM (py_%s, i_%s, py_e_%s);\n" n n n;
pr " }\n"
+ | CBArrayAndLen (Extent64 n, len) ->
+ pr " py_%s = PyList_New (%s);\n" n len;
+ pr " size_t i_%s;\n" n;
+ pr " for (i_%s = 0; i_%s < %s; ++i_%s) {\n" n n len n;
+ pr " PyObject *py_e_%s = Py_BuildValue (\"OO\",\n" n;
+ pr " PyLong_FromUnsignedLong (%s[i_%s].length),\n" n n;
+ pr " PyLong_FromUnsignedLong (%s[i_%s].flags));\n" n n;
+ pr " if (!py_e_%s) { PyErr_PrintEx (0); goto out; }\n" n;
+ pr " PyList_SET_ITEM (py_%s, i_%s, py_e_%s);\n" n n n;
+ pr " }\n"
| CBBytesIn (n, len) ->
pr " py_%s = nbd_internal_py_get_subview (data->view, %s, %s);\n" n n len;
pr " if (!py_%s) { PyErr_PrintEx (0); goto out; }\n" n
@@ -201,6 +213,7 @@ let
List.map (
function
| CBArrayAndLen (UInt32 n, _) -> "O", sprintf "py_%s" n
+ | CBArrayAndLen (Extent64 n, _) -> "O", sprintf "py_%s" n
| CBBytesIn (n, _) -> "O", sprintf "py_%s" n
| CBInt n -> "i", n
| CBInt64 n -> "L", n
@@ -249,7 +262,8 @@ let
pr " out:\n";
List.iter (
function
- | CBArrayAndLen (UInt32 n, _) ->
+ | CBArrayAndLen (UInt32 n, _)
+ | CBArrayAndLen (Extent64 n, _) ->
pr " Py_XDECREF (py_%s);\n" n
| CBBytesIn (n, _) ->
pr " Py_XDECREF (py_%s);\n" n
@@ -302,6 +316,7 @@ let
pr ".callback = %s_wrapper, .free = free_user_data" cbname);
pr " };\n"
| Enum (n, _) -> pr " int %s;\n" n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Flags (n, _) ->
pr " uint32_t %s_u32;\n" n;
pr " unsigned int %s; /* really uint32_t */\n" n
@@ -358,6 +373,7 @@ let
"O", sprintf "&%s" n, sprintf "py_%s->buf, py_%s->len" n n
| Closure { cbname } -> "O", sprintf "&py_%s_fn" cbname, cbname
| Enum (n, _) -> "i", sprintf "&%s" n, n
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Flags (n, _) -> "I", sprintf "&%s" n, sprintf "%s_u32" n
| Fd n | Int n -> "i", sprintf "&%s" n, n
| Int64 n -> "L", sprintf "&%s" n, sprintf "%s_i64" n
@@ -449,6 +465,7 @@ let
pr " if (!chunk_user_data->view) goto out;\n"
)
| Enum _ -> ()
+ | Extent64 _ -> ()
| Flags (n, _) -> pr " %s_u32 = %s;\n" n n
| Fd _ | Int _ -> ()
| Int64 n -> pr " %s_i64 = %s;\n" n n
@@ -547,6 +564,7 @@ let
| Closure { cbname } ->
pr " free_user_data (%s_user_data);\n" cbname
| Enum _ -> ()
+ | Extent64 _ -> ()
| Flags _ -> ()
| Fd _ | Int _ -> ()
| Int64 _ -> ()
@@ -834,6 +852,7 @@ let
| BytesPersistOut (n, _) -> n, None
| Closure { cbname } -> cbname, None
| Enum (n, _) -> n, None
+ | Extent64 _ -> assert false (* only used in extent64_closure *)
| Flags (n, _) -> n, None
| Fd n | Int n -> n, None
| Int64 n -> n, None
@@ -133,6 +133,26 @@ nbd_internal_ocaml_alloc_int64_from_uint32_array (uint32_t *a, size_t len)
CAMLreturn (rv);
}
+value
+nbd_internal_ocaml_alloc_extent64_array (nbd_extent *a, size_t len)
+{
+ CAMLparam0 ();
+ CAMLlocal3 (s, v, rv);
+ size_t i;
+
+ rv = caml_alloc (len, 0);
+ for (i = 0; i < len; ++i) {
+ s = caml_alloc (2, 0);
+ v = caml_copy_int64 (a[i].length);
+ Store_field (s, 0, v);
+ v = caml_copy_int64 (a[i].flags);
+ Store_field (s, 1, v);
+ Store_field (rv, i, s);
+ }
+
+ CAMLreturn (rv);
+}
+
/* Convert a Unix.sockaddr to a C struct sockaddr. */
void
nbd_internal_unix_sockaddr_to_sa (value sockaddrv,
@@ -1,5 +1,5 @@
/* NBD client library in userspace
- * Copyright (C) 2013-2019 Red Hat Inc.
+ * Copyright (C) 2013-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -63,6 +63,7 @@ extern void nbd_internal_ocaml_raise_closed (const char *func) Noreturn;
extern const char **nbd_internal_ocaml_string_list (value);
extern value nbd_internal_ocaml_alloc_int64_from_uint32_array (uint32_t *,
size_t);
+extern value nbd_internal_ocaml_alloc_extent64_array (nbd_extent *, size_t);
extern void nbd_internal_unix_sockaddr_to_sa (value, struct sockaddr_storage *,
socklen_t *);
extern void nbd_internal_ocaml_exception_in_wrapper (const char *, value);
@@ -1,5 +1,5 @@
/* libnbd golang handle.
- * Copyright (C) 2013-2021 Red Hat Inc.
+ * Copyright (C) 2013-2022 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -58,6 +58,12 @@ func (h *Libnbd) String() string {
return "&Libnbd{}"
}
+/* Used for block status callback. */
+type LibnbdExtent struct {
+ Length uint64 // length of the extent
+ Flags uint64 // flags describing properties of the extent
+}
+
/* All functions (except Close) return ([result,] LibnbdError). */
type LibnbdError struct {
Op string // operation which failed