Simple macro encapsulating the process for freeing a callback.
---
generator/states-reply-simple.c | 4 +--
generator/states-reply-structured.c | 42 +++++++++--------------------
generator/states-reply.c | 4 +--
generator/states.c | 4 +--
lib/aio.c | 17 ++++--------
lib/debug.c | 6 +----
lib/internal.h | 14 ++++++++++
7 files changed, 35 insertions(+), 56 deletions(-)
diff --git a/generator/states-reply-simple.c b/generator/states-reply-simple.c
index 7f2775d..8905367 100644
--- a/generator/states-reply-simple.c
+++ b/generator/states-reply-simple.c
@@ -69,9 +69,7 @@
cmd->offset, LIBNBD_READ_DATA,
&error) == -1)
cmd->error = error ? error : EPROTO;
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */
+ FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE (%^FINISH_COMMAND);
diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index 7c4d63e..62ae3ad 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -307,11 +307,8 @@
&scratch) == -1)
if (cmd->error == 0)
cmd->error = scratch;
- if (flags & NBD_REPLY_FLAG_DONE) {
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */
- }
+ if (flags & NBD_REPLY_FLAG_DONE)
+ FREE_CALLBACK (cmd->cb.fn.chunk);
}
}
@@ -401,11 +398,8 @@
LIBNBD_READ_DATA, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE) {
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */
- }
+ if (flags & NBD_REPLY_FLAG_DONE)
+ FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE (%FINISH);
@@ -469,11 +463,8 @@
LIBNBD_READ_HOLE, &error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE) {
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- cmd->cb.fn.chunk.callback = NULL; /* because we've freed it */
- }
+ if (flags & NBD_REPLY_FLAG_DONE)
+ FREE_CALLBACK (cmd->cb.fn.chunk);
}
SET_NEXT_STATE(%FINISH);
@@ -527,11 +518,8 @@
&error) == -1)
if (cmd->error == 0)
cmd->error = error ? error : EPROTO;
- if (flags & NBD_REPLY_FLAG_DONE) {
- if (cmd->cb.fn.extent.free)
- cmd->cb.fn.extent.free (cmd->cb.fn.extent.user_data);
- cmd->cb.fn.extent.callback = NULL; /* because we've freed it */
- }
+ if (flags & NBD_REPLY_FLAG_DONE)
+ FREE_CALLBACK (cmd->cb.fn.extent);
}
else
/* Emit a debug message, but ignore it. */
@@ -548,16 +536,10 @@
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.callback) {
- if (cmd->cb.fn.extent.free)
- cmd->cb.fn.extent.free (cmd->cb.fn.extent.user_data);
- }
- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) {
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- }
- cmd->cb.fn.extent.callback = NULL;
- cmd->cb.fn.chunk.callback = NULL;
+ if (cmd->type == NBD_CMD_BLOCK_STATUS)
+ FREE_CALLBACK (cmd->cb.fn.extent);
+ if (cmd->type == NBD_CMD_READ)
+ FREE_CALLBACK (cmd->cb.fn.chunk);
SET_NEXT_STATE (%^FINISH_COMMAND);
}
else {
diff --git a/generator/states-reply.c b/generator/states-reply.c
index d6bd7be..b8bf0ce 100644
--- a/generator/states-reply.c
+++ b/generator/states-reply.c
@@ -174,9 +174,7 @@ save_reply_state (struct nbd_handle *h)
assert (cmd->type != NBD_CMD_DISC);
r = cmd->cb.completion.callback (cmd->cb.completion.user_data, &error);
- if (cmd->cb.completion.free)
- cmd->cb.completion.free (cmd->cb.completion.user_data);
- cmd->cb.completion.callback = NULL; /* because we've freed it */
+ FREE_CALLBACK (cmd->cb.completion);
switch (r) {
case -1:
if (error)
diff --git a/generator/states.c b/generator/states.c
index 444a082..98c10b3 100644
--- a/generator/states.c
+++ b/generator/states.c
@@ -127,9 +127,7 @@ void abort_commands (struct nbd_handle *h,
assert (cmd->type != NBD_CMD_DISC);
r = cmd->cb.completion.callback (cmd->cb.completion.user_data, &error);
- if (cmd->cb.completion.free)
- cmd->cb.completion.free (cmd->cb.completion.user_data);
- cmd->cb.completion.callback = NULL; /* because we've freed it */
+ FREE_CALLBACK (cmd->cb.completion);
switch (r) {
case -1:
if (error)
diff --git a/lib/aio.c b/lib/aio.c
index df493bc..38a27d0 100644
--- a/lib/aio.c
+++ b/lib/aio.c
@@ -32,18 +32,11 @@ void
nbd_internal_retire_and_free_command (struct command *cmd)
{
/* Free the callbacks. */
- if (cmd->type == NBD_CMD_BLOCK_STATUS && cmd->cb.fn.extent.callback) {
- if (cmd->cb.fn.extent.free)
- cmd->cb.fn.extent.free (cmd->cb.fn.extent.user_data);
- }
- if (cmd->type == NBD_CMD_READ && cmd->cb.fn.chunk.callback) {
- if (cmd->cb.fn.chunk.free)
- cmd->cb.fn.chunk.free (cmd->cb.fn.chunk.user_data);
- }
- if (cmd->cb.completion.callback) {
- if (cmd->cb.completion.free)
- cmd->cb.completion.free (cmd->cb.completion.user_data);
- }
+ if (cmd->type == NBD_CMD_BLOCK_STATUS)
+ FREE_CALLBACK (cmd->cb.fn.extent);
+ if (cmd->type == NBD_CMD_READ)
+ FREE_CALLBACK (cmd->cb.fn.chunk);
+ FREE_CALLBACK (cmd->cb.completion);
free (cmd);
}
diff --git a/lib/debug.c b/lib/debug.c
index 1dd6240..e1ec675 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -41,11 +41,7 @@ nbd_unlocked_get_debug (struct nbd_handle *h)
int
nbd_unlocked_clear_debug_callback (struct nbd_handle *h)
{
- if (h->debug_callback.callback)
- if (h->debug_callback.free)
- /* ignore return value */
- h->debug_callback.free (h->debug_callback.user_data);
- h->debug_callback.callback = NULL;
+ FREE_CALLBACK (h->debug_callback);
return 0;
}
diff --git a/lib/internal.h b/lib/internal.h
index 5996a4f..305158e 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -273,6 +273,20 @@ struct command {
uint32_t error; /* Local errno value */
};
+/* Free a callback.
+ *
+ * Note this works for any type of callback because the basic layout
+ * of the struct is the same for all of them. Therefore casting cb to
+ * nbd_completion_callback does not change the effective code.
+ */
+#define FREE_CALLBACK(cb) \
+ do { \
+ nbd_completion_callback *_cb = (nbd_completion_callback *)&(cb); \
+ if (_cb->callback != NULL && _cb->free != NULL) \
+ _cb->free (_cb->user_data); \
+ _cb->callback = NULL; \
+ } while (0)
+
/* aio.c */
extern void nbd_internal_retire_and_free_command (struct command *);
--
2.22.0