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 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs