[Libguestfs] [libnbd PATCH] lib: Reduce number of read/block_status callbacks

Eric Blake eblake at redhat.com
Thu Jul 25 21:55:49 UTC 2019


When the server sets NBD_REPLY_FLAG_DONE on a data or block status
chunk, we can use that fact to pass (VALID|FREE) and avoid a separate
callback later just for FREE.
---

As I've been promising in other threads...

 generator/states-reply-structured.c | 33 +++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/generator/states-reply-structured.c b/generator/states-reply-structured.c
index 2ef8d20..20b0e9e 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -18,6 +18,19 @@

 /* State machine for parsing structured replies from the server. */

+static unsigned
+valid_flags (struct nbd_handle *h)
+{
+  unsigned valid = LIBNBD_CALLBACK_VALID;
+  uint16_t flags = be16toh (h->sbuf.sr.structured_reply.flags);
+
+  if (flags & NBD_REPLY_FLAG_DONE)
+    valid |= LIBNBD_CALLBACK_FREE;
+  return valid;
+}
+
+/*----- End of prologue. -----*/
+
 /* STATE MACHINE */ {
  REPLY.STRUCTURED_REPLY.START:
   /* We've only read the simple_reply.  The structured_reply is longer,
@@ -293,16 +306,19 @@
       }
       if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read) {
         int scratch = error;
+        unsigned valid = valid_flags (h);

         /* Different from successful reads: inform the callback about the
          * current error rather than any earlier one. If the callback fails
          * without setting errno, then use the server's error below.
          */
-        if (cmd->cb.fn.read (LIBNBD_CALLBACK_VALID, cmd->cb.fn_user_data,
+        if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
                              cmd->data + (offset - cmd->offset),
                              0, offset, LIBNBD_READ_ERROR, &scratch) == -1)
           if (cmd->error == 0)
             cmd->error = scratch;
+        if (valid & LIBNBD_CALLBACK_FREE)
+          cmd->cb.fn.read = NULL; /* because we've freed it */
       }
     }

@@ -384,13 +400,16 @@
     assert (cmd); /* guaranteed by CHECK */
     if (cmd->cb.fn.read) {
       int error = cmd->error;
+      unsigned valid = valid_flags (h);

-      if (cmd->cb.fn.read (LIBNBD_CALLBACK_VALID, cmd->cb.fn_user_data,
+      if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
                            cmd->data + (offset - cmd->offset),
                            length - sizeof offset, offset,
                            LIBNBD_READ_DATA, &error) == -1)
         if (cmd->error == 0)
           cmd->error = error ? error : EPROTO;
+      if (valid & LIBNBD_CALLBACK_FREE)
+        cmd->cb.fn.read = NULL; /* because we've freed it */
     }

     SET_NEXT_STATE (%FINISH);
@@ -446,13 +465,16 @@
     memset (cmd->data + offset, 0, length);
     if (cmd->cb.fn.read) {
       int error = cmd->error;
+      unsigned valid = valid_flags (h);

-      if (cmd->cb.fn.read (LIBNBD_CALLBACK_VALID, cmd->cb.fn_user_data,
+      if (cmd->cb.fn.read (valid, cmd->cb.fn_user_data,
                            cmd->data + offset, length,
                            cmd->offset + offset,
                            LIBNBD_READ_HOLE, &error) == -1)
         if (cmd->error == 0)
           cmd->error = error ? error : EPROTO;
+      if (valid & LIBNBD_CALLBACK_FREE)
+        cmd->cb.fn.read = NULL; /* because we've freed it */
     }

     SET_NEXT_STATE(%FINISH);
@@ -498,12 +520,15 @@
     if (meta_context) {
       /* Call the caller's extent function. */
       int error = cmd->error;
+      unsigned valid = valid_flags (h);

-      if (cmd->cb.fn.extent (LIBNBD_CALLBACK_VALID, cmd->cb.fn_user_data,
+      if (cmd->cb.fn.extent (valid, cmd->cb.fn_user_data,
                              meta_context->name, cmd->offset,
                              &h->bs_entries[1], (length-4) / 4, &error) == -1)
         if (cmd->error == 0)
           cmd->error = error ? error : EPROTO;
+      if (valid & LIBNBD_CALLBACK_FREE)
+        cmd->cb.fn.extent = NULL; /* because we've freed it */
     }
     else
       /* Emit a debug message, but ignore it. */
-- 
2.20.1




More information about the Libguestfs mailing list