[Libguestfs] [libnbd PATCH 4/8] states: Prepare for read callback

Eric Blake
Tue, 18 Jun 2019 00:07:54 -0000

The next patch will add a new 'nbd_aio_pread_callback' function for
allowing the user more immediate access as each chunk of a structured
reply read is received. But before we do that, let's refactor the
command code. This includes a revert of 12843a1a, since the read
callback will need both a buffer and the user's opaque object at the
same time.
---
 generator/states-reply-structured.c |  8 ++++----
 lib/internal.h                      | 17 +++++++++++++----
 lib/rw.c                            |  9 ++++++---
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/generator/states-reply-structured.c
b/generator/states-reply-structured.c
index 6740400..657106e 100644
--- a/generator/states-reply-structured.c
+++ b/generator/states-reply-structured.c
@@ -123,7 +123,7 @@
       set_error (0, "invalid length in NBD_REPLY_TYPE_BLOCK_STATUS");
       return -1;
     }
-    if (cmd->extent_fn == NULL) {
+    if (cmd->cb.fn.extent == NULL) {
       SET_NEXT_STATE (%.DEAD);
       set_error (0, "not expecting NBD_REPLY_TYPE_BLOCK_STATUS
here");
       return -1;
@@ -375,7 +375,7 @@
     length = be32toh (h->sbuf.sr.structured_reply.length);

     assert (cmd); /* guaranteed by CHECK */
-    assert (cmd->extent_fn);
+    assert (cmd->cb.fn.extent);
     assert (h->bs_entries);
     assert (length >= 12);

@@ -401,8 +401,8 @@
       if (meta_context) {
         /* Call the caller's extent function. */
         errno = 0;
-        if (cmd->extent_fn (cmd->data, meta_context->name,
cmd->offset,
-                            &h->bs_entries[1], (length-4) / 4) == -1)
+        if (cmd->cb.fn.extent (cmd->cb.opaque, meta_context->name,
cmd->offset,
+                               &h->bs_entries[1], (length-4) / 4) == -1)
           cmd->error = errno ? errno : EPROTO;
       }
       else
diff --git a/lib/internal.h b/lib/internal.h
index 1f8f789..cb0e170 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -231,7 +231,16 @@ struct socket {
   const struct socket_ops *ops;
 };

-typedef int (*extent_fn) (void *data, const char *metacontext, uint64_t offset,
uint32_t *entries, size_t nr_entries);
+typedef int (*extent_fn) (void *data, const char *metacontext, uint64_t offset,
+                          uint32_t *entries, size_t nr_entries);
+
+struct command_cb {
+  void *opaque;
+  union {
+    extent_fn extent;
+    /* More to come */
+  } fn;
+};

 struct command_in_flight {
   struct command_in_flight *next;
@@ -240,8 +249,8 @@ struct command_in_flight {
   uint64_t handle;
   uint64_t offset;
   uint32_t count;
-  void *data; /* Buffer for read/write, opaque for block status */
-  extent_fn extent_fn;
+  void *data; /* Buffer for read/write */
+  struct command_cb cb;
   bool data_seen; /* For read, true if at least one data chunk seen */
   uint32_t error; /* Local errno value */
 };
@@ -300,7 +309,7 @@ extern const char *nbd_internal_name_of_nbd_cmd (uint16_t
type);
 extern int64_t nbd_internal_command_common (struct nbd_handle *h,
                                             uint16_t flags, uint16_t type,
                                             uint64_t offset, uint64_t count,
-                                            void *data, extent_fn extent);
+                                            void *data, struct command_cb *cb);

 /* socket.c */
 struct socket *nbd_internal_socket_create (int fd);
diff --git a/lib/rw.c b/lib/rw.c
index ad9c8a0..dc81c57 100644
--- a/lib/rw.c
+++ b/lib/rw.c
@@ -143,7 +143,7 @@ int64_t
 nbd_internal_command_common (struct nbd_handle *h,
                              uint16_t flags, uint16_t type,
                              uint64_t offset, uint64_t count, void *data,
-                             extent_fn extent)
+                             struct command_cb *cb)
 {
   struct command_in_flight *cmd, *prev_cmd;

@@ -183,7 +183,8 @@ nbd_internal_command_common (struct nbd_handle *h,
   cmd->offset = offset;
   cmd->count = count;
   cmd->data = data;
-  cmd->extent_fn = extent;
+  if (cb)
+    cmd->cb = *cb;

   /* If structured replies were negotiated then we trust the server to
    * send back sufficient data to cover the whole buffer.  It's tricky
@@ -360,6 +361,8 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
                                void *data, extent_fn extent,
                                uint32_t flags)
 {
+  struct command_cb cb = { .opaque = data, .fn.extent = extent, };
+
   if (!h->structured_replies) {
     set_error (ENOTSUP, "server does not support structured
replies");
     return -1;
@@ -383,5 +386,5 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
   }

   return nbd_internal_command_common (h, flags, NBD_CMD_BLOCK_STATUS, offset,
-                                      count, data, extent);
+                                      count, NULL, &cb);
 }
--
2.20.1