[Libguestfs] [PATCH libnbd 3/4] lib: Add FREE_CALLBACK macro.

Richard W.M. Jones rjones at redhat.com
Tue Aug 13 22:37:00 UTC 2019


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




More information about the Libguestfs mailing list