The definition of functions that take a callback is changed so that the callback and user_data are combined into a single structure, eg: int64_t nbd_aio_pread (struct nbd_handle *h, void *buf, size_t count, uint64_t offset, - int (*completion_callback) (/*..*/), void *user_data, + nbd_completion_callback completion_callback, uint32_t flags); Several nbd_*_callback structures are defined. The one corresponding to the example above is: typedef struct { void *user_data; int (*callback) (unsigned valid_flag, void *user_data, int *error); } nbd_completion_callback; The nbd_aio_pread function can now be called using: nbd_aio_pread (nbd, buf, sizeof buf, offset, (nbd_completion_callback) { .callback = my_fn, .user_data = my_data }, 0); Note that the whole structure is passed by value not by reference. For OClosure only, a NULL callback can be passed using this macro: nbd_aio_pread (nbd, buf, sizeof buf, offset, NBD_NULL_CALLBACK(completion), 0); --- docs/libnbd.pod | 27 ++++++--- examples/batched-read-write.c | 5 +- examples/glib-main-loop.c | 6 +- examples/strict-structured-reads.c | 3 +- examples/threaded-reads-and-writes.c | 6 +- generator/generator | 89 ++++++++++++++-------------- generator/states-reply-simple.c | 13 ++-- generator/states-reply-structured.c | 64 ++++++++++---------- generator/states-reply.c | 8 +-- generator/states.c | 8 +-- interop/dirty-bitmap.c | 11 +++- interop/structured-read.c | 9 ++- lib/aio.c | 21 ++++--- lib/debug.c | 16 ++--- lib/internal.h | 3 - lib/rw.c | 60 ++++++++----------- tests/aio-parallel-load.c | 6 +- tests/aio-parallel.c | 6 +- tests/closure-lifetimes.c | 14 +++-- tests/errors.c | 9 ++- tests/meta-base-allocation.c | 11 +++- tests/oldstyle.c | 6 +- tests/server-death.c | 7 ++- 23 files changed, 226 insertions(+), 182 deletions(-) diff --git a/docs/libnbd.pod b/docs/libnbd.pod index b38def0..9177825 100644 --- a/docs/libnbd.pod +++ b/docs/libnbd.pod @@ -598,14 +598,25 @@ will use your login name): =head1 CALLBACKS -Some libnbd calls take function pointers (eg. -C<nbd_set_debug_callback>, C<nbd_aio_pread>). Libnbd can call these -functions while processing. - -Callbacks have an opaque C<void *user_data> pointer. This is passed -as the second parameter to the callback. The opaque pointer is only -used from the C API, since in other languages you can use closures to -achieve the same outcome. +Some libnbd calls take callbacks (eg. C<nbd_set_debug_callback>, +C<nbd_aio_pread>). Libnbd can call these functions while processing. + +In the C API these libnbd calls take a structure which contains the +function pointer and an optional opaque C<void *user_data> pointer: + + nbd_aio_pread (nbd, buf, sizeof buf, offset, + (nbd_completion_callback) { .callback = my_fn, + .user_data = my_data }, + 0); + +If you don't want the callback, either set C<.callback> to C<NULL> or +use the equivalent macro C<NBD_NULL_CALLBACK()> defined in C<libnbd.h>: + + nbd_aio_pread (nbd, buf, sizeof buf, offset, + NBD_NULL_CALLBACK(completion), 0); + +From other languages the structure and opaque pointer are not needed +because you can use closures to achieve the same effect. =head2 Callback lifetimes diff --git a/examples/batched-read-write.c b/examples/batched-read-write.c index 378c2e0..a6063af 100644 --- a/examples/batched-read-write.c +++ b/examples/batched-read-write.c @@ -53,12 +53,13 @@ try_deadlock (void *arg) /* Issue commands. */ cookies[0] = nbd_aio_pread (nbd, in, packetsize, 0, - NULL, NULL, 0); + NBD_NULL_CALLBACK(completion), 0); if (cookies[0] == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); goto error; } - cookies[1] = nbd_aio_pwrite (nbd, out, packetsize, packetsize, NULL, NULL, 0); + cookies[1] = nbd_aio_pwrite (nbd, out, packetsize, packetsize, + NBD_NULL_CALLBACK(completion), 0); if (cookies[1] == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); goto error; diff --git a/examples/glib-main-loop.c b/examples/glib-main-loop.c index 7b4d215..a8e8ceb 100644 --- a/examples/glib-main-loop.c +++ b/examples/glib-main-loop.c @@ -384,7 +384,8 @@ read_data (gpointer user_data) if (nbd_aio_pread (gssrc->nbd, buffers[i].data, BUFFER_SIZE, buffers[i].offset, - finished_read, &buffers[i], 0) == -1) { + (nbd_completion_callback) { .callback = finished_read, .user_data = &buffers[i] }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } @@ -428,7 +429,8 @@ write_data (gpointer user_data) buffer->state = BUFFER_WRITING; if (nbd_aio_pwrite (gsdest->nbd, buffer->data, BUFFER_SIZE, buffer->offset, - finished_write, buffer, 0) == -1) { + (nbd_completion_callback) { .callback = finished_write, .user_data = buffer }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } diff --git a/examples/strict-structured-reads.c b/examples/strict-structured-reads.c index 4bc63b8..d7c3e1b 100644 --- a/examples/strict-structured-reads.c +++ b/examples/strict-structured-reads.c @@ -236,7 +236,8 @@ main (int argc, char *argv[]) *d = (struct data) { .offset = offset, .count = maxsize, .flags = flags, .remaining = r, }; if (nbd_aio_pread_structured (nbd, buf, sizeof buf, offset, - read_chunk, d, read_verify, d, + (nbd_chunk_callback) { .callback = read_chunk, .user_data = d }, + (nbd_completion_callback) { .callback = read_verify, .user_data = d }, flags) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/examples/threaded-reads-and-writes.c b/examples/threaded-reads-and-writes.c index 7626a02..6ae1dd2 100644 --- a/examples/threaded-reads-and-writes.c +++ b/examples/threaded-reads-and-writes.c @@ -252,9 +252,11 @@ start_thread (void *arg) offset = rand () % (exportsize - size); cmd = rand () & 1; if (cmd == 0) - cookie = nbd_aio_pwrite (nbd, buf, size, offset, NULL, NULL, 0); + cookie = nbd_aio_pwrite (nbd, buf, size, offset, + NBD_NULL_CALLBACK(completion), 0); else - cookie = nbd_aio_pread (nbd, buf, size, offset, NULL, NULL, 0); + cookie = nbd_aio_pread (nbd, buf, size, offset, + NBD_NULL_CALLBACK(completion), 0); if (cookie == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); goto error; diff --git a/generator/generator b/generator/generator index 4d3d7ad..ea32929 100755 --- a/generator/generator +++ b/generator/generator @@ -3226,10 +3226,7 @@ let rec print_arg_list ?(handle = false) ?(types = true) args optargs = pr "%s" len | Closure { cbname; cbargs } -> if types then pr "nbd_%s_callback " cbname; - pr "%s_callback" cbname; - pr ", "; - if types then pr "void *"; - pr "%s_user_data" cbname + pr "%s_callback" cbname | Enum (n, _) -> if types then pr "int "; pr "%s" n @@ -3271,10 +3268,7 @@ let rec print_arg_list ?(handle = false) ?(types = true) args optargs = match optarg with | OClosure { cbname; cbargs } -> if types then pr "nbd_%s_callback " cbname; - pr "%s_callback" cbname; - pr ", "; - if types then pr "void *"; - pr "%s_user_data" cbname + pr "%s_callback" cbname | OFlags (n, _) -> if types then pr "uint32_t "; pr "%s" n @@ -3337,14 +3331,19 @@ let print_cbarg_list ?(valid_flag = true) ?(types = true) cbargs = ) cbargs; pr ")" -(* Callback typedefs in <libnbd.h> *) -let print_closure_typedefs () = +(* Callback structs/typedefs in <libnbd.h> *) +let print_closure_structs () = List.iter ( fun { cbname; cbargs } -> - pr "typedef int (*nbd_%s_callback) " cbname; + pr "typedef struct {\n"; + pr " void *user_data;\n"; + pr " int (*callback) "; print_cbarg_list cbargs; pr ";\n"; + pr "} nbd_%s_callback;\n" cbname; + pr "\n"; ) all_closures; + pr "#define NBD_NULL_CALLBACK(name) ((nbd_## name ##_callback) { .callback = NULL })\n"; pr "\n" let print_extern_and_define name args optargs ret = @@ -3434,7 +3433,7 @@ let generate_include_libnbd_h () = pr "extern int nbd_get_errno (void);\n"; pr "#define LIBNBD_HAVE_NBD_GET_ERRNO 1\n"; pr "\n"; - print_closure_typedefs (); + print_closure_structs (); List.iter ( fun (name, { args; optargs; ret }) -> print_extern_and_define name args optargs ret @@ -3566,7 +3565,7 @@ let generate_lib_api_c () = let value = match errcode with | Some value -> value | None -> assert false in - pr " if (%s_callback == NULL) {\n" cbname; + pr " if (%s_callback.callback == NULL) {\n" cbname; pr " set_error (EFAULT, \"%%s cannot be NULL\", \"%s\");\n" cbname; pr " ret = %s;\n" value; pr " goto out;\n"; @@ -3678,7 +3677,8 @@ let generate_lib_api_c () = ) args; List.iter ( function - | OClosure { cbname } -> pr ", %s_callback ? \"<fun>\" : \"NULL\"" cbname + | OClosure { cbname } -> + pr ", %s_callback.callback ? \"<fun>\" : \"NULL\"" cbname | OFlags (n, _) -> pr ", %s" n ) optargs; pr ");\n" @@ -4156,7 +4156,8 @@ let print_python_binding name { args; optargs; ret; may_set_error } = n; pr " struct py_aio_buffer *%s_buf;\n" n | Closure { cbname } -> - pr " PyObject *%s_user_data;\n" cbname + pr " nbd_%s_callback %s = { .callback = %s_wrapper };\n" + cbname cbname cbname | Enum (n, _) -> pr " int %s;\n" n | Flags (n, _) -> pr " uint32_t %s_u32;\n" n; @@ -4188,7 +4189,8 @@ let print_python_binding name { args; optargs; ret; may_set_error } = List.iter ( function | OClosure { cbname } -> - pr " PyObject *%s_user_data;\n" cbname + pr " nbd_%s_callback %s = { .callback = %s_wrapper };\n" + cbname cbname cbname | OFlags (n, _) -> pr " uint32_t %s_u32;\n" n; pr " unsigned int %s; /* really uint32_t */\n" n @@ -4231,7 +4233,7 @@ let print_python_binding name { args; optargs; ret; may_set_error } = | BytesIn (n, _) | BytesPersistIn (n, _) | BytesPersistOut (n, _) -> pr ", &%s" n | BytesOut (_, count) -> pr ", &%s" count - | Closure { cbname } -> pr ", &%s_user_data" cbname + | Closure { cbname } -> pr ", &%s.user_data" cbname | Enum (n, _) -> pr ", &%s" n | Flags (n, _) -> pr ", &%s" n | Int n -> pr ", &%s" n @@ -4246,7 +4248,7 @@ let print_python_binding name { args; optargs; ret; may_set_error } = ) args; List.iter ( function - | OClosure { cbname } -> pr ", &%s_user_data" cbname + | OClosure { cbname } -> pr ", &%s.user_data" cbname | OFlags (n, _) -> pr ", &%s" n ) optargs; pr "))\n"; @@ -4263,8 +4265,8 @@ let print_python_binding name { args; optargs; ret; may_set_error } = pr " %s_buf = nbd_internal_py_get_aio_buffer (%s);\n" n n | Closure { cbname } -> pr " /* Increment refcount since pointer may be saved by libnbd. */\n"; - pr " Py_INCREF (%s_user_data);\n" cbname; - pr " if (!PyCallable_Check (%s_user_data)) {\n" cbname; + pr " Py_INCREF (%s.user_data);\n" cbname; + pr " if (!PyCallable_Check (%s.user_data)) {\n" cbname; pr " PyErr_SetString (PyExc_TypeError,\n"; pr " \"callback parameter %s is not callable\");\n" cbname; pr " return NULL;\n"; @@ -4289,15 +4291,17 @@ let print_python_binding name { args; optargs; ret; may_set_error } = List.iter ( function | OClosure { cbname } -> - pr " if (%s_user_data != Py_None) {\n" cbname; + pr " if (%s.user_data != Py_None) {\n" cbname; pr " /* Increment refcount since pointer may be saved by libnbd. */\n"; - pr " Py_INCREF (%s_user_data);\n" cbname; - pr " if (!PyCallable_Check (%s_user_data)) {\n" cbname; + pr " Py_INCREF (%s.user_data);\n" cbname; + pr " if (!PyCallable_Check (%s.user_data)) {\n" cbname; pr " PyErr_SetString (PyExc_TypeError,\n"; pr " \"callback parameter %s is not callable\");\n" cbname; pr " return NULL;\n"; pr " }\n"; - pr " }\n" + pr " }\n"; + pr " else\n"; + pr " %s.callback = NULL; /* we're not going to call it */\n" cbname | OFlags (n, _) -> pr " %s_u32 = %s;\n" n n ) optargs; @@ -4310,9 +4314,7 @@ let print_python_binding name { args; optargs; ret; may_set_error } = | BytesOut (n, count) -> pr ", %s, %s" n count | BytesPersistIn (n, _) | BytesPersistOut (n, _) -> pr ", %s_buf->data, %s_buf->len" n n - | Closure { cbname } -> - pr ", %s_wrapper" cbname; - pr ", %s_user_data" cbname + | Closure { cbname } -> pr ", %s" cbname | Enum (n, _) -> pr ", %s" n | Flags (n, _) -> pr ", %s_u32" n | Int n -> pr ", %s" n @@ -4327,9 +4329,7 @@ let print_python_binding name { args; optargs; ret; may_set_error } = ) args; List.iter ( function - | OClosure { cbname } -> - pr ", %s_user_data != Py_None ? %s_wrapper : NULL" cbname cbname; - pr ", %s_user_data != Py_None ? %s_user_data : NULL" cbname cbname + | OClosure { cbname } -> pr ", %s" cbname | OFlags (n, _) -> pr ", %s_u32" n ) optargs; pr ");\n"; @@ -5125,17 +5125,18 @@ let print_ocaml_binding (name, { args; optargs; ret }) = List.iter ( function | OClosure { cbname } -> - pr " const void *%s_callback = NULL;\n" cbname; - pr " value *%s_user_data = NULL;\n" cbname; + pr " nbd_%s_callback %s_callback = {0};\n" cbname cbname; pr " if (%sv != Val_int (0)) { /* Some closure */\n" cbname; pr " /* The function may save a reference to the closure, so we\n"; pr " * must treat it as a possible GC root.\n"; pr " */\n"; - pr " %s_user_data = malloc (sizeof (value));\n" cbname; - pr " if (%s_user_data == NULL) caml_raise_out_of_memory ();\n" cbname; - pr " *%s_user_data = Field (%sv, 0);\n" cbname cbname; - pr " caml_register_generational_global_root (%s_user_data);\n" cbname; - pr " %s_callback = %s_wrapper;\n" cbname cbname; + pr " %s_callback.user_data = malloc (sizeof (value));\n" cbname; + pr " if (%s_callback.user_data == NULL)\n" cbname; + pr " caml_raise_out_of_memory ();\n"; + pr " *(value *)%s_callback.user_data = Field (%sv, 0);\n" + cbname cbname; + pr " caml_register_generational_global_root (%s_callback.user_data);\n" cbname; + pr " %s_callback.callback = %s_wrapper;\n" cbname cbname; pr " }\n"; | OFlags (n, { flag_prefix }) -> pr " uint32_t %s;\n" n; @@ -5168,12 +5169,14 @@ let print_ocaml_binding (name, { args; optargs; ret }) = pr " /* The function may save a reference to the closure, so we\n"; pr " * must treat it as a possible GC root.\n"; pr " */\n"; - pr " value *%s_user_data;\n" cbname; - pr " %s_user_data = malloc (sizeof (value));\n" cbname; - pr " if (%s_user_data == NULL) caml_raise_out_of_memory ();\n" cbname; - pr " *%s_user_data = %sv;\n" cbname cbname; - pr " caml_register_generational_global_root (%s_user_data);\n" cbname; - pr " const void *%s_callback = %s_wrapper;\n" cbname cbname + pr " nbd_%s_callback %s_callback = { .callback = %s_wrapper };\n" + cbname cbname cbname; + pr " %s_callback.user_data = malloc (sizeof (value));\n" cbname; + pr " if (%s_callback.user_data == NULL) caml_raise_out_of_memory ();\n" + cbname; + pr " *(value *)%s_callback.user_data = %sv;\n" cbname cbname; + pr " caml_register_generational_global_root (%s_callback.user_data);\n" + cbname | Enum (n, { enum_prefix }) -> pr " int %s = %s_val (%sv);\n" n enum_prefix n | Flags (n, { flag_prefix }) -> diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c index 9b249ab..f1d3c62 100644 --- a/generator/states-reply-simple.c +++ b/generator/states-reply-simple.c @@ -60,16 +60,17 @@ case 0: /* guaranteed by START */ assert (cmd); - if (cmd->cb.fn.chunk) { + if (cmd->cb.fn.chunk.callback) { int error = 0; assert (cmd->error == 0); - if (cmd->cb.fn.chunk (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, - cmd->cb.fn_user_data, - cmd->data, cmd->count, - cmd->offset, LIBNBD_READ_DATA, &error) == -1) + if (cmd->cb.fn.chunk.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, + cmd->cb.fn.chunk.user_data, + cmd->data, cmd->count, + cmd->offset, LIBNBD_READ_DATA, + &error) == -1) cmd->error = error ? error : EPROTO; - cmd->cb.fn.chunk = NULL; /* because we've freed it */ + cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */ } SET_NEXT_STATE (%^FINISH_COMMAND); diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c index cdd9f10..92d6b5f 100644 --- a/generator/states-reply-structured.c +++ b/generator/states-reply-structured.c @@ -168,7 +168,7 @@ valid_flags (struct nbd_handle *h) set_error (0, "invalid length in NBD_REPLY_TYPE_BLOCK_STATUS"); return 0; } - if (cmd->cb.fn.extent == NULL) { + if (cmd->cb.fn.extent.callback == NULL) { SET_NEXT_STATE (%.DEAD); set_error (0, "not expecting NBD_REPLY_TYPE_BLOCK_STATUS here"); return 0; @@ -304,7 +304,7 @@ valid_flags (struct nbd_handle *h) offset, cmd->offset, cmd->count); return 0; } - if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) { + if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) { int scratch = error; unsigned valid = valid_flags (h); @@ -312,13 +312,14 @@ valid_flags (struct nbd_handle *h) * current error rather than any earlier one. If the callback fails * without setting errno, then use the server's error below. */ - if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, - cmd->data + (offset - cmd->offset), - 0, offset, LIBNBD_READ_ERROR, &scratch) == -1) + if (cmd->cb.fn.chunk.callback (valid, cmd->cb.fn.chunk.user_data, + cmd->data + (offset - cmd->offset), + 0, offset, LIBNBD_READ_ERROR, + &scratch) == -1) if (cmd->error == 0) cmd->error = scratch; if (valid & LIBNBD_CALLBACK_FREE) - cmd->cb.fn.chunk = NULL; /* because we've freed it */ + cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */ } } @@ -398,18 +399,18 @@ valid_flags (struct nbd_handle *h) offset = be64toh (h->sbuf.sr.payload.offset_data.offset); assert (cmd); /* guaranteed by CHECK */ - if (cmd->cb.fn.chunk) { + if (cmd->cb.fn.chunk.callback) { int error = cmd->error; unsigned valid = valid_flags (h); - if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, - cmd->data + (offset - cmd->offset), - length - sizeof offset, offset, - LIBNBD_READ_DATA, &error) == -1) + if (cmd->cb.fn.chunk.callback (valid, cmd->cb.fn.chunk.user_data, + cmd->data + (offset - cmd->offset), + length - sizeof offset, offset, + LIBNBD_READ_DATA, &error) == -1) if (cmd->error == 0) cmd->error = error ? error : EPROTO; if (valid & LIBNBD_CALLBACK_FREE) - cmd->cb.fn.chunk = NULL; /* because we've freed it */ + cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */ } SET_NEXT_STATE (%FINISH); @@ -463,18 +464,18 @@ valid_flags (struct nbd_handle *h) * them as an extension, and this works even when length == 0. */ memset (cmd->data + offset, 0, length); - if (cmd->cb.fn.chunk) { + if (cmd->cb.fn.chunk.callback) { int error = cmd->error; unsigned valid = valid_flags (h); - if (cmd->cb.fn.chunk (valid, cmd->cb.fn_user_data, - cmd->data + offset, length, - cmd->offset + offset, - LIBNBD_READ_HOLE, &error) == -1) + if (cmd->cb.fn.chunk.callback (valid, cmd->cb.fn.chunk.user_data, + cmd->data + offset, length, + cmd->offset + offset, + LIBNBD_READ_HOLE, &error) == -1) if (cmd->error == 0) cmd->error = error ? error : EPROTO; if (valid & LIBNBD_CALLBACK_FREE) - cmd->cb.fn.chunk = NULL; /* because we've freed it */ + cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */ } SET_NEXT_STATE(%FINISH); @@ -499,7 +500,7 @@ valid_flags (struct nbd_handle *h) assert (cmd); /* guaranteed by CHECK */ assert (cmd->type == NBD_CMD_BLOCK_STATUS); - assert (cmd->cb.fn.extent); + assert (cmd->cb.fn.extent.callback); assert (h->bs_entries); assert (length >= 12); @@ -522,13 +523,14 @@ valid_flags (struct nbd_handle *h) int error = cmd->error; unsigned valid = valid_flags (h); - if (cmd->cb.fn.extent (valid, cmd->cb.fn_user_data, - meta_context->name, cmd->offset, - &h->bs_entries[1], (length-4) / 4, &error) == -1) + if (cmd->cb.fn.extent.callback (valid, cmd->cb.fn.extent.user_data, + meta_context->name, cmd->offset, + &h->bs_entries[1], (length-4) / 4, + &error) == -1) if (cmd->error == 0) cmd->error = error ? error : EPROTO; if (valid & LIBNBD_CALLBACK_FREE) - cmd->cb.fn.extent = NULL; /* because we've freed it */ + cmd->cb.fn.extent.callback = NULL; /* because we've freed it */ } else /* Emit a debug message, but ignore it. */ @@ -545,13 +547,15 @@ valid_flags (struct nbd_handle *h) flags = be16toh (h->sbuf.sr.structured_reply.flags); if (flags & NBD_REPLY_FLAG_DONE) { - if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent) - cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, - NULL, 0, NULL, 0, NULL); - if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) - cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, - NULL, 0, 0, 0, NULL); - cmd->cb.fn.chunk = NULL; + if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent.callback) + cmd->cb.fn.extent.callback (LIBNBD_CALLBACK_FREE, + cmd->cb.fn.extent.user_data, + NULL, 0, NULL, 0, NULL); + if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) + cmd->cb.fn.chunk.callback (LIBNBD_CALLBACK_FREE, + cmd->cb.fn.chunk.user_data, + NULL, 0, 0, 0, NULL); + cmd->cb.fn.chunk.callback = NULL; SET_NEXT_STATE (%^FINISH_COMMAND); } else { diff --git a/generator/states-reply.c b/generator/states-reply.c index 09adfed..e6b479a 100644 --- a/generator/states-reply.c +++ b/generator/states-reply.c @@ -168,14 +168,14 @@ save_reply_state (struct nbd_handle *h) retire = cmd->type == NBD_CMD_DISC; /* Notify the user */ - if (cmd->cb.completion) { + if (cmd->cb.completion.callback) { int error = cmd->error; int r; assert (cmd->type != NBD_CMD_DISC); - r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, - cmd->cb.user_data, &error); - cmd->cb.completion = NULL; /* because we've freed it */ + r = cmd->cb.completion.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, + cmd->cb.completion.user_data, &error); + cmd->cb.completion.callback = NULL; /* because we've freed it */ switch (r) { case -1: if (error) diff --git a/generator/states.c b/generator/states.c index 9ed57ae..22b0304 100644 --- a/generator/states.c +++ b/generator/states.c @@ -121,14 +121,14 @@ void abort_commands (struct nbd_handle *h, bool retire = cmd->type == NBD_CMD_DISC; next = cmd->next; - if (cmd->cb.completion) { + if (cmd->cb.completion.callback) { int error = cmd->error ? cmd->error : ENOTCONN; int r; assert (cmd->type != NBD_CMD_DISC); - r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, - cmd->cb.user_data, &error); - cmd->cb.completion = NULL; /* because we've freed it */ + r = cmd->cb.completion.callback (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE, + cmd->cb.completion.user_data, &error); + cmd->cb.completion.callback = NULL; /* because we've freed it */ switch (r) { case -1: if (error) diff --git a/interop/dirty-bitmap.c b/interop/dirty-bitmap.c index aca0564..5a22adc 100644 --- a/interop/dirty-bitmap.c +++ b/interop/dirty-bitmap.c @@ -140,14 +140,17 @@ main (int argc, char *argv[]) } data = (struct data) { .count = 2, }; - if (nbd_block_status (nbd, exportsize, 0, cb, &data, 0) == -1) { + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } assert (data.seen_base && data.seen_dirty); data = (struct data) { .req_one = true, .count = 2, }; - if (nbd_block_status (nbd, exportsize, 0, cb, &data, + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, LIBNBD_CMD_FLAG_REQ_ONE) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); @@ -156,7 +159,9 @@ main (int argc, char *argv[]) /* Trigger a failed callback, to prove connection stays up. */ data = (struct data) { .count = 2, .fail = true, }; - if (nbd_block_status (nbd, exportsize, 0, cb, &data, 0) != -1) { + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, + 0) != -1) { fprintf (stderr, "unexpected block status success\n"); exit (EXIT_FAILURE); } diff --git a/interop/structured-read.c b/interop/structured-read.c index 0b189d1..31aadbe 100644 --- a/interop/structured-read.c +++ b/interop/structured-read.c @@ -147,7 +147,8 @@ main (int argc, char *argv[]) memset (rbuf, 2, sizeof rbuf); data = (struct data) { .count = 2, }; - if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, read_cb, &data, + if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, + (nbd_chunk_callback) { .callback = read_cb, .user_data = &data }, 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); @@ -157,7 +158,8 @@ main (int argc, char *argv[]) /* Repeat with DF flag. */ memset (rbuf, 2, sizeof rbuf); data = (struct data) { .df = true, .count = 1, }; - if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, read_cb, &data, + if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, + (nbd_chunk_callback) { .callback = read_cb, .user_data = &data }, LIBNBD_CMD_FLAG_DF) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); @@ -170,7 +172,8 @@ main (int argc, char *argv[]) */ memset (rbuf, 2, sizeof rbuf); data = (struct data) { .count = 2, .fail = true, }; - if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, read_cb, &data, + if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2048, + (nbd_chunk_callback) { .callback = read_cb, .user_data = &data }, 0) != -1) { fprintf (stderr, "unexpected pread callback success\n"); exit (EXIT_FAILURE); diff --git a/lib/aio.c b/lib/aio.c index c141de6..5017ee6 100644 --- a/lib/aio.c +++ b/lib/aio.c @@ -32,15 +32,18 @@ void nbd_internal_retire_and_free_command (struct command *cmd) { /* Free the callbacks. */ - if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent) - cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, - NULL, 0, NULL, 0, NULL); - if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk) - cmd->cb.fn.chunk (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data, - NULL, 0, 0, 0, NULL); - if (cmd->cb.completion) - cmd->cb.completion (LIBNBD_CALLBACK_FREE, cmd->cb.user_data, - NULL); + if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent.callback) + cmd->cb.fn.extent.callback (LIBNBD_CALLBACK_FREE, + cmd->cb.fn.extent.user_data, + NULL, 0, NULL, 0, NULL); + if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) + cmd->cb.fn.chunk.callback (LIBNBD_CALLBACK_FREE, + cmd->cb.fn.chunk.user_data, + NULL, 0, 0, 0, NULL); + if (cmd->cb.completion.callback) + cmd->cb.completion.callback (LIBNBD_CALLBACK_FREE, + cmd->cb.completion.user_data, + NULL); free (cmd); } diff --git a/lib/debug.c b/lib/debug.c index c1decb2..7753394 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -41,23 +41,22 @@ nbd_unlocked_get_debug (struct nbd_handle *h) int nbd_unlocked_clear_debug_callback (struct nbd_handle *h) { - if (h->debug_callback) + if (h->debug_callback.callback) /* ignore return value */ - h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL); - h->debug_callback = NULL; - h->debug_data = NULL; + h->debug_callback.callback (LIBNBD_CALLBACK_FREE, + h->debug_callback.user_data, NULL, NULL); + h->debug_callback.callback = NULL; return 0; } int nbd_unlocked_set_debug_callback (struct nbd_handle *h, - nbd_debug_callback debug_callback, void *data) + nbd_debug_callback debug_callback) { /* This can't fail at the moment - see implementation above. */ nbd_unlocked_clear_debug_callback (h); h->debug_callback = debug_callback; - h->debug_data = data; return 0; } @@ -87,9 +86,10 @@ nbd_internal_debug (struct nbd_handle *h, const char *fs, ...) if (r == -1) goto out; - if (h->debug_callback) + if (h->debug_callback.callback) /* ignore return value */ - h->debug_callback (LIBNBD_CALLBACK_VALID, h->debug_data, context, msg); + h->debug_callback.callback (LIBNBD_CALLBACK_VALID, + h->debug_callback.user_data, context, msg); else fprintf (stderr, "libnbd: debug: %s: %s: %s\n", h->hname, context ? : "unknown", msg); diff --git a/lib/internal.h b/lib/internal.h index 301b798..5996a4f 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -85,7 +85,6 @@ struct nbd_handle { /* For debugging. */ bool debug; nbd_debug_callback debug_callback; - void *debug_data; /* State machine. * @@ -257,9 +256,7 @@ struct command_cb { nbd_extent_callback extent; nbd_chunk_callback chunk; } fn; - void *fn_user_data; /* associated with one of the fn callbacks above */ nbd_completion_callback completion; - void *user_data; /* associated with the completion callback */ }; struct command { diff --git a/lib/rw.c b/lib/rw.c index dbd4e8c..9881701 100644 --- a/lib/rw.c +++ b/lib/rw.c @@ -49,7 +49,8 @@ nbd_unlocked_pread (struct nbd_handle *h, void *buf, { int64_t cookie; - cookie = nbd_unlocked_aio_pread (h, buf, count, offset, NULL, NULL, flags); + cookie = nbd_unlocked_aio_pread (h, buf, count, offset, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -60,14 +61,15 @@ nbd_unlocked_pread (struct nbd_handle *h, void *buf, int nbd_unlocked_pread_structured (struct nbd_handle *h, void *buf, size_t count, uint64_t offset, - nbd_chunk_callback chunk, void *user_data, + nbd_chunk_callback chunk, uint32_t flags) { int64_t cookie; cookie = nbd_unlocked_aio_pread_structured (h, buf, count, offset, - chunk, user_data, - NULL, NULL, flags); + chunk, + NBD_NULL_CALLBACK(completion), + flags); if (cookie == -1) return -1; @@ -81,7 +83,8 @@ nbd_unlocked_pwrite (struct nbd_handle *h, const void *buf, { int64_t cookie; - cookie = nbd_unlocked_aio_pwrite (h, buf, count, offset, NULL, NULL, flags); + cookie = nbd_unlocked_aio_pwrite (h, buf, count, offset, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -94,7 +97,7 @@ nbd_unlocked_flush (struct nbd_handle *h, uint32_t flags) { int64_t cookie; - cookie = nbd_unlocked_aio_flush (h, NULL, NULL, flags); + cookie = nbd_unlocked_aio_flush (h, NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -108,7 +111,8 @@ nbd_unlocked_trim (struct nbd_handle *h, { int64_t cookie; - cookie = nbd_unlocked_aio_trim (h, count, offset, NULL, NULL, flags); + cookie = nbd_unlocked_aio_trim (h, count, offset, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -122,7 +126,8 @@ nbd_unlocked_cache (struct nbd_handle *h, { int64_t cookie; - cookie = nbd_unlocked_aio_cache (h, count, offset, NULL, NULL, flags); + cookie = nbd_unlocked_aio_cache (h, count, offset, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -136,7 +141,8 @@ nbd_unlocked_zero (struct nbd_handle *h, { int64_t cookie; - cookie = nbd_unlocked_aio_zero (h, count, offset, NULL, NULL, flags); + cookie = nbd_unlocked_aio_zero (h, count, offset, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -147,13 +153,13 @@ nbd_unlocked_zero (struct nbd_handle *h, int nbd_unlocked_block_status (struct nbd_handle *h, uint64_t count, uint64_t offset, - nbd_extent_callback extent, void *user_data, + nbd_extent_callback extent, uint32_t flags) { int64_t cookie; - cookie = nbd_unlocked_aio_block_status (h, count, offset, extent, user_data, - NULL, NULL, flags); + cookie = nbd_unlocked_aio_block_status (h, count, offset, extent, + NBD_NULL_CALLBACK(completion), flags); if (cookie == -1) return -1; @@ -257,10 +263,9 @@ int64_t nbd_unlocked_aio_pread (struct nbd_handle *h, void *buf, size_t count, uint64_t offset, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; /* We could silently accept flag DF, but it really only makes sense * with callbacks, because otherwise there is no observable change @@ -279,15 +284,11 @@ int64_t nbd_unlocked_aio_pread_structured (struct nbd_handle *h, void *buf, size_t count, uint64_t offset, nbd_chunk_callback chunk, - void *read_user_data, nbd_completion_callback completion, - void *callback_user_data, uint32_t flags) { struct command_cb cb = { .fn.chunk = chunk, - .fn_user_data = read_user_data, - .completion = completion, - .user_data = callback_user_data, }; + .completion = completion }; if ((flags & ~LIBNBD_CMD_FLAG_DF) != 0) { set_error (EINVAL, "invalid flag: %" PRIu32, flags); @@ -308,10 +309,9 @@ int64_t nbd_unlocked_aio_pwrite (struct nbd_handle *h, const void *buf, size_t count, uint64_t offset, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; if (nbd_unlocked_is_read_only (h) == 1) { set_error (EINVAL, "server does not support write operations"); @@ -336,10 +336,9 @@ nbd_unlocked_aio_pwrite (struct nbd_handle *h, const void *buf, int64_t nbd_unlocked_aio_flush (struct nbd_handle *h, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; if (nbd_unlocked_can_flush (h) != 1) { set_error (EINVAL, "server does not support flush operations"); @@ -359,10 +358,9 @@ int64_t nbd_unlocked_aio_trim (struct nbd_handle *h, uint64_t count, uint64_t offset, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; if (nbd_unlocked_is_read_only (h) == 1) { set_error (EINVAL, "server does not support write operations"); @@ -393,10 +391,9 @@ int64_t nbd_unlocked_aio_cache (struct nbd_handle *h, uint64_t count, uint64_t offset, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; /* Actually according to the NBD protocol document, servers do exist * that support NBD_CMD_CACHE but don't advertise the @@ -420,10 +417,9 @@ int64_t nbd_unlocked_aio_zero (struct nbd_handle *h, uint64_t count, uint64_t offset, nbd_completion_callback completion, - void *user_data, uint32_t flags) { - struct command_cb cb = { .completion = completion, .user_data = user_data, }; + struct command_cb cb = { .completion = completion }; if (nbd_unlocked_is_read_only (h) == 1) { set_error (EINVAL, "server does not support write operations"); @@ -454,15 +450,11 @@ int64_t nbd_unlocked_aio_block_status (struct nbd_handle *h, uint64_t count, uint64_t offset, nbd_extent_callback extent, - void *extent_user_data, nbd_completion_callback completion, - void *callback_user_data, uint32_t flags) { struct command_cb cb = { .fn.extent = extent, - .fn_user_data = extent_user_data, - .completion = completion, - .user_data = callback_user_data }; + .completion = completion }; if (!h->structured_replies) { set_error (ENOTSUP, "server does not support structured replies"); diff --git a/tests/aio-parallel-load.c b/tests/aio-parallel-load.c index 1f48324..0d67c36 100644 --- a/tests/aio-parallel-load.c +++ b/tests/aio-parallel-load.c @@ -255,11 +255,13 @@ start_thread (void *arg) offset = rand () % (EXPORTSIZE - buf_size); cmd = rand () & 1; if (cmd == 0) { - cookie = nbd_aio_pwrite (nbd, buf, buf_size, offset, NULL, NULL, 0); + cookie = nbd_aio_pwrite (nbd, buf, buf_size, offset, + NBD_NULL_CALLBACK(completion), 0); status->bytes_sent += buf_size; } else { - cookie = nbd_aio_pread (nbd, buf, buf_size, offset, NULL, NULL, 0); + cookie = nbd_aio_pread (nbd, buf, buf_size, offset, + NBD_NULL_CALLBACK(completion), 0); status->bytes_received += buf_size; } if (cookie == -1) { diff --git a/tests/aio-parallel.c b/tests/aio-parallel.c index fb4d695..f6f13e6 100644 --- a/tests/aio-parallel.c +++ b/tests/aio-parallel.c @@ -271,12 +271,14 @@ start_thread (void *arg) + (rand () % (status->length[i] - BUFFERSIZE)); cmd = rand () & 1; if (cmd == 0) { - cookie = nbd_aio_pwrite (nbd, buf, BUFFERSIZE, offset, NULL, NULL, 0); + cookie = nbd_aio_pwrite (nbd, buf, BUFFERSIZE, offset, + NBD_NULL_CALLBACK(completion), 0); status->bytes_sent += BUFFERSIZE; memcpy (&ramdisk[offset], buf, BUFFERSIZE); } else { - cookie = nbd_aio_pread (nbd, buf, BUFFERSIZE, offset, NULL, NULL, 0); + cookie = nbd_aio_pread (nbd, buf, BUFFERSIZE, offset, + NBD_NULL_CALLBACK(completion), 0); status->bytes_received += BUFFERSIZE; } if (cookie == -1) { diff --git a/tests/closure-lifetimes.c b/tests/closure-lifetimes.c index 60809d4..e21a0e9 100644 --- a/tests/closure-lifetimes.c +++ b/tests/closure-lifetimes.c @@ -101,10 +101,10 @@ main (int argc, char *argv[]) nbd = nbd_create (); if (nbd == NULL) NBD_ERROR; - nbd_set_debug_callback (nbd, debug_fn, NULL); + nbd_set_debug_callback (nbd, (nbd_debug_callback) { .callback = debug_fn }); assert (debug_fn_free == 0); - nbd_set_debug_callback (nbd, debug_fn, NULL); + nbd_set_debug_callback (nbd, (nbd_debug_callback) { .callback = debug_fn}); assert (debug_fn_free == 1); debug_fn_free = 0; @@ -117,8 +117,9 @@ main (int argc, char *argv[]) if (nbd_connect_command (nbd, nbdkit) == -1) NBD_ERROR; cookie = nbd_aio_pread_structured (nbd, buf, sizeof buf, 0, - read_cb, NULL, - completion_cb, NULL, 0); + (nbd_chunk_callback) { .callback = read_cb }, + (nbd_completion_callback) { .callback = completion_cb }, + 0); if (cookie == -1) NBD_ERROR; assert (read_cb_free == 0); assert (completion_cb_free == 0); @@ -144,8 +145,9 @@ main (int argc, char *argv[]) if (nbd_connect_command (nbd, nbdkit_delay) == -1) NBD_ERROR; cookie = nbd_aio_pread_structured (nbd, buf, sizeof buf, 0, - read_cb, NULL, - completion_cb, NULL, 0); + (nbd_chunk_callback) { .callback = read_cb }, + (nbd_completion_callback) { .callback = completion_cb }, + 0); if (cookie == -1) NBD_ERROR; nbd_kill_command (nbd, 0); nbd_close (nbd); diff --git a/tests/errors.c b/tests/errors.c index e442738..21ec919 100644 --- a/tests/errors.c +++ b/tests/errors.c @@ -222,7 +222,8 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } check (ERANGE, "nbd_pread: "); - if (nbd_aio_pwrite (nbd, buf, MAXSIZE, 0, NULL, NULL, 0) != -1) { + if (nbd_aio_pwrite (nbd, buf, MAXSIZE, 0, + NBD_NULL_CALLBACK(completion), 0) != -1) { fprintf (stderr, "%s: test failed: " "nbd_aio_pwrite did not fail with oversize request\n", argv[0]); @@ -245,11 +246,13 @@ main (int argc, char *argv[]) * command at a time and stalls on the first), then queue multiple * disconnects. */ - if (nbd_aio_pwrite (nbd, buf, 2 * 1024 * 1024, 0, NULL, NULL, 0) == -1) { + if (nbd_aio_pwrite (nbd, buf, 2 * 1024 * 1024, 0, + NBD_NULL_CALLBACK(completion), 0) == -1) { fprintf (stderr, "%s: %s\n", argv[0], nbd_get_error ()); exit (EXIT_FAILURE); } - if (nbd_aio_pwrite (nbd, buf, 2 * 1024 * 1024, 0, NULL, NULL, 0) == -1) { + if (nbd_aio_pwrite (nbd, buf, 2 * 1024 * 1024, 0, + NBD_NULL_CALLBACK(completion), 0) == -1) { fprintf (stderr, "%s: %s\n", argv[0], nbd_get_error ()); exit (EXIT_FAILURE); } diff --git a/tests/meta-base-allocation.c b/tests/meta-base-allocation.c index c36a77f..d4e331c 100644 --- a/tests/meta-base-allocation.c +++ b/tests/meta-base-allocation.c @@ -101,19 +101,24 @@ main (int argc, char *argv[]) /* Read the block status. */ id = 1; - if (nbd_block_status (nbd, 65536, 0, check_extent, &id, 0) == -1) { + if (nbd_block_status (nbd, 65536, 0, + (nbd_extent_callback) { .callback = check_extent, .user_data = &id }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } id = 2; - if (nbd_block_status (nbd, 1024, 32768-512, check_extent, &id, 0) == -1) { + if (nbd_block_status (nbd, 1024, 32768-512, + (nbd_extent_callback) { .callback = check_extent, .user_data = &id }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } id = 3; - if (nbd_block_status (nbd, 1024, 32768-512, check_extent, &id, + if (nbd_block_status (nbd, 1024, 32768-512, + (nbd_extent_callback) { .callback = check_extent, .user_data = &id }, LIBNBD_CMD_FLAG_REQ_ONE) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); diff --git a/tests/oldstyle.c b/tests/oldstyle.c index afbda61..ff2ee97 100644 --- a/tests/oldstyle.c +++ b/tests/oldstyle.c @@ -131,7 +131,8 @@ main (int argc, char *argv[]) /* Test again for callback operation. */ memset (rbuf, 0, sizeof rbuf); if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2 * sizeof rbuf, - pread_cb, &calls, 0) == -1) { + (nbd_chunk_callback) { .callback = pread_cb, .user_data = &calls }, + 0) == -1) { fprintf (stderr, "%s\n", nbd_get_error ()); exit (EXIT_FAILURE); } @@ -147,7 +148,8 @@ main (int argc, char *argv[]) /* Also test that callback errors are reflected correctly. */ if (nbd_pread_structured (nbd, rbuf, sizeof rbuf, 2 * sizeof rbuf, - pread_cb, &calls, 0) != -1) { + (nbd_chunk_callback) { .callback = pread_cb, .user_data = &calls }, + 0) != -1) { fprintf (stderr, "%s: expected failure from callback\n", argv[0]); exit (EXIT_FAILURE); } diff --git a/tests/server-death.c b/tests/server-death.c index 1559753..f7684ac 100644 --- a/tests/server-death.c +++ b/tests/server-death.c @@ -77,12 +77,15 @@ main (int argc, char *argv[]) /* Issue a read and trim that should not complete yet. Set up the * trim to auto-retire via callback. */ - if ((cookie = nbd_aio_pread (nbd, buf, sizeof buf, 0, NULL, NULL, 0)) == -1) { + if ((cookie = nbd_aio_pread (nbd, buf, sizeof buf, 0, + NBD_NULL_CALLBACK(completion), 0)) == -1) { fprintf (stderr, "%s: test failed: nbd_aio_pread: %s\n", argv[0], nbd_get_error ()); exit (EXIT_FAILURE); } - if (nbd_aio_trim (nbd, sizeof buf, 0, callback, NULL, 0) == -1) { + if (nbd_aio_trim (nbd, sizeof buf, 0, + (nbd_completion_callback) { .callback = callback }, + 0) == -1) { fprintf (stderr, "%s: test failed: nbd_aio_trim: %s\n", argv[0], nbd_get_error ()); exit (EXIT_FAILURE); -- 2.22.0