[Libguestfs] [PATCH libnbd 4/7] lib: Allow closure user_data to be associated with a free callback.

Richard W.M. Jones rjones at redhat.com
Mon Aug 12 16:08:48 UTC 2019


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




More information about the Libguestfs mailing list