Mechanical change: Wherever we call any closure with the
LIBNBD_CALLBACK_FREE function, we also call nbd_internal_free_callback
with the closure's user_data. This allows calls to associate a free
callback with any closure via its user_data pointer.
---
generator/states-reply-simple.c | 1 +
generator/states-reply-structured.c | 24 ++++++++++++++++++------
generator/states-reply.c | 1 +
generator/states.c | 1 +
lib/aio.c | 4 ++++
lib/debug.c | 4 +++-
lib/handle.c | 4 +++-
7 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c
index 9b249ab..9684bc4 100644
--- a/generator/states-reply-simple.c
+++ b/generator/states-reply-simple.c
@@ -69,6 +69,7 @@
cmd->data, cmd->count,
cmd->offset, LIBNBD_READ_DATA, &error) == -1)
cmd->error = error ? error : EPROTO;
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
cmd->cb.fn.chunk = NULL; /* because we've freed it */
}
diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index cdd9f10..b016cd7 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -317,8 +317,10 @@ valid_flags (struct nbd_handle *h)
0, offset, LIBNBD_READ_ERROR, &scratch) == -1)
if (cmd->error == 0)
cmd->error = scratch;
- if (valid & LIBNBD_CALLBACK_FREE)
+ if (valid & LIBNBD_CALLBACK_FREE) {
cmd->cb.fn.chunk = NULL; /* because we've freed it */
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
}
}
@@ -408,8 +410,10 @@ valid_flags (struct nbd_handle *h)
LIBNBD_READ_DATA, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (valid & LIBNBD_CALLBACK_FREE)
+ if (valid & LIBNBD_CALLBACK_FREE) {
cmd->cb.fn.chunk = NULL; /* because we've freed it */
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
}
SET_NEXT_STATE (%FINISH);
@@ -473,8 +477,10 @@ valid_flags (struct nbd_handle *h)
LIBNBD_READ_HOLE, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (valid & LIBNBD_CALLBACK_FREE)
+ if (valid & LIBNBD_CALLBACK_FREE) {
cmd->cb.fn.chunk = NULL; /* because we've freed it */
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
}
SET_NEXT_STATE(%FINISH);
@@ -527,8 +533,10 @@ valid_flags (struct nbd_handle *h)
&h->bs_entries[1], (length-4) / 4, &error) ==
-1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (valid & LIBNBD_CALLBACK_FREE)
+ if (valid & LIBNBD_CALLBACK_FREE) {
cmd->cb.fn.extent = NULL; /* because we've freed it */
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
}
else
/* Emit a debug message, but ignore it. */
@@ -545,12 +553,16 @@ 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)
+ 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)
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
+ 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);
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ }
cmd->cb.fn.chunk = NULL;
SET_NEXT_STATE (%^FINISH_COMMAND);
}
diff --git a/generator/states-reply.c b/generator/states-reply.c
index 389317e..d5cba1a 100644
--- a/generator/states-reply.c
+++ b/generator/states-reply.c
@@ -175,6 +175,7 @@ save_reply_state (struct nbd_handle *h)
assert (cmd->type != NBD_CMD_DISC);
r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
cmd->cb.user_data, &error);
+ nbd_internal_free_callback (h, cmd->cb.user_data);
cmd->cb.completion = NULL; /* because we've freed it */
switch (r) {
case -1:
diff --git a/generator/states.c b/generator/states.c
index a11c1d1..313d2c9 100644
--- a/generator/states.c
+++ b/generator/states.c
@@ -128,6 +128,7 @@ void abort_commands (struct nbd_handle *h,
assert (cmd->type != NBD_CMD_DISC);
r = cmd->cb.completion (LIBNBD_CALLBACK_VALID|LIBNBD_CALLBACK_FREE,
cmd->cb.user_data, &error);
+ nbd_internal_free_callback (h, cmd->cb.user_data);
cmd->cb.completion = NULL; /* because we've freed it */
switch (r) {
case -1:
diff --git a/lib/aio.c b/lib/aio.c
index 1d26be9..8aa4547 100644
--- a/lib/aio.c
+++ b/lib/aio.c
@@ -43,6 +43,10 @@ nbd_internal_retire_and_free_command (struct nbd_handle *h,
cmd->cb.completion (LIBNBD_CALLBACK_FREE, cmd->cb.user_data,
NULL);
+ /* Free the closures if there's an associated free callback. */
+ nbd_internal_free_callback (h, cmd->cb.fn_user_data);
+ nbd_internal_free_callback (h, cmd->cb.user_data);
+
/* Free the persistent buffer if there is one and if there's an
* associated free callback.
*/
diff --git a/lib/debug.c b/lib/debug.c
index ad4d9cb..34d4184 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -42,9 +42,11 @@ int
nbd_unlocked_set_debug_callback (struct nbd_handle *h,
nbd_debug_callback debug_callback, void *data)
{
- if (h->debug_callback)
+ if (h->debug_callback) {
/* ignore return value */
h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
+ nbd_internal_free_callback (h, h->debug_data);
+ }
h->debug_callback = debug_callback;
h->debug_data = data;
return 0;
diff --git a/lib/handle.c b/lib/handle.c
index 0f50e38..5a47bd8 100644
--- a/lib/handle.c
+++ b/lib/handle.c
@@ -113,8 +113,10 @@ nbd_close (struct nbd_handle *h)
return;
/* Free user callbacks first. */
- if (h->debug_callback)
+ if (h->debug_callback) {
h->debug_callback (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
+ nbd_internal_free_callback (h, h->debug_data);
+ }
h->debug_callback = NULL;
free (h->bs_entries);
--
2.22.0